Ffmpeg simple video player and ffmpeg player
Refer to Lei Xiaohua's simplest FFMPEG-based video player.
There is always a problem when porting code to my linux environment, So I simply analyzed and transplanted Raytheon's code for debugging from start to end.
Development Environment:
Operating System: ubuntu14
Ffmpeg version: 3.2.2
Sdl version: 2
I typed the code by referring to Raytheon's code. In this process, I found that I still need to print the code. Nothing can be taken to run it successfully. Especially when designing an interface, it is best to return the running result of the returned value, and the outgoing memory needs to be transmitted through parameters.
The printing of Errors still requires more details. In the future, when writing large programs, you should develop the habit of adding logs, which is of great help to debugging programs.
Insert the following code:
Note: after running the program for a period of time, it will become black and white. Check the cause again.
Compile and run:
Gcc-g main. c-o test-I/usr/local/ffmpeg/include-L/usr/local/ffmpeg/lib-lavutil-lavformat-lavcodec-lz-lavutil-lswscale-L/usr /lib/x86_64-linux-gnu-lSDL2-lSDL2main
(The path is based on your own installation path.-g is used for GDB debugging)
./Test
1 #ifdef _cplusplus
2 extern "C"
3 {
4 #endif
5
6 #include <stdio.h>
7 #include <libavcodec / avcodec.h>
8 #include <libavformat / avformat.h>
9 #include <libavutil / avutil.h>
10 #include <libswscale / swscale.h>
11 #include <libavutil / avutil.h>
12 #include <libavutil / imgutils.h>
13 #include <SDL2 / SDL.h>
14
15 // Whether to output YUV420P content to file
16 #define OUTPUT_YUV420P 0
17 // File path to play
18 #define filename "/home/sns/cuc_ieschool.flv"
19 // File path to output YUV420P content
20 #define outfilename "/home/sns/output.yuv"
twenty one
22 int main (int argc, char ** argv)
twenty three {
24 // variable definition ***************************************** ************************
25 AVFormatContext * pFormatCtx;
26 int i, videoStream;
27 AVCodecContext * pCodecCtx;
28 AVCodec * pCodec;
29 AVFrame * pFrame;
30 AVFrame * pFrameYUV;
31 uint8_t * buffer;
32 int numBytes;
33
34 SDL_Window * screen;
35 SDL_Renderer * sdlRender;
36 SDL_Texture * sdlTexture;
37 SDL_Rect sdlRect;
38 int frameFinished;
39 AVPacket packet;
40 i = 0;
41 struct SwsContext * img_convert_ctx;
42 int err_code;
43 char buf [1024];
44 FILE * fp_yuv;
45 int y_size;
46 // *********************************************** ********************************
47 av_register_all ();
48 // 1. Open video file ************************************** *******
49 pFormatCtx = avformat_alloc_context ();
50 err_code = avformat_open_input (& pFormatCtx, filename, NULL, NULL);
51 if (err_code! = 0)
52 {// Failed to open file
53 av_strerror (err_code, buf, 1024);
54 printf ("coundn't open the file!, Error code =% d (% s) \ n", err_code, buf);
55 return -1;
56}
57 if (avformat_find_stream_info (pFormatCtx, NULL) <0)
58 {
59 printf ("Couldn't find stream information. \ N");
60 return -1;
61}
62 // 2 、 Find the first video stream ****************************
63 videoStream = -1;
64 for (i = 0; i <pFormatCtx-> nb_streams; i ++)
65 {
66 if (pFormatCtx-> streams [i]-> codec-> codec_type == AVMEDIA_TYPE_VIDEO)
67 {
68 videoStream = i; // Get the index of the video stream
69 break;
70}
71}
72 if (videoStream == -1)
73 {
74 printf ("Didn't find a video stream. \ N");
75 return -1;
76}
77 / * 3. Get a codec context from the video stream, which contains all the information of the codec and a
78 points to the real codec, and then we find this decoder * /
79 pCodecCtx = pFormatCtx-> streams [videoStream]-> codec;
80 pCodec = avcodec_find_decoder (pCodecCtx-> codec_id);
81 if (pCodec == NULL)
82 {
83 fprintf (stderr, "Unsupported codec! \ N");
84 return -1;
85}
86 // 4. Open the codec
87 if (avcodec_open2 (pCodecCtx, pCodec, NULL) <0)
88 {
89 printf ("cann't open the codec! \ N");
90 return -1;
91}
92 // 5. Allocate two video frames, one to save the original video frame and one to save the video frame in the specified format (the frame is converted from the original frame)
93 pFrame = av_frame_alloc ();
94 if (pFrame == NULL)
95 {
96 printf ("pFrame alloc fail! \ N");
97 return -1;
98}
99 pFrameYUV = av_frame_alloc ();
100 if (pFrameYUV == NULL)
101 {
102 printf ("pFrameYUV alloc fail! \ N");
103 return -1;
104}
105 // 6. Get the memory size of a frame of video and allocate memory, and fill in YUV data
106 numBytes = av_image_get_buffer_size (AV_PIX_FMT_YUV420P, pCodecCtx-> width,
107 pCodecCtx-> height, 1);
108 buffer = (uint8_t *) av_mallocz (numBytes * sizeof (uint8_t));
109 if (! Buffer)
110 {
111 printf ("numBytes:% d, buffer malloc 's mem \ n", numBytes);
112 return -1;
113}
114 // Print information
115 printf ("--------------- File Information ---------------- \ n");
116 av_dump_format (pFormatCtx, 0, filename, 0);
117 printf ("---------------------------------------------- --- \ n ");
118 av_image_fill_arrays (pFrameYUV-> data, pFrameYUV-> linesize, buffer,
119 AV_PIX_FMT_YUV420P, pCodecCtx-> width, pCodecCtx-> height, 1);
120 // 7. Get the context of the specified conversion format ******************************
121 img_convert_ctx = sws_getContext (pCodecCtx-> width, pCodecCtx-> height,
122 pCodecCtx-> pix_fmt, pCodecCtx-> width, pCodecCtx-> height,
123 AV_PIX_FMT_YUV420P,
124 SWS_BICUBIC,
125 NULL, NULL, NULL);
126 if (img_convert_ctx == NULL)
127 {
128 fprintf (stderr, "Cannot initialize the conversion context! \ N");
129 return -1;
130}
131 // *********************************************** ************
132 #if OUTPUT_YUV420P
133 fp_yuv = fopen (outfilename, "wb +");
134 #endif
135 // 8, SDL initialization and preparation of multiple windows and other preparations
136 if (SDL_Init (SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_VIDEO))
137 {
138 fprintf (stderr, "Could not initialize SDL-% s \ n", SDL_GetError ());
139 return -1;
140}
141 // Use SDL_CreateWindow instead of SDL_SetVideoMode
142 // Create a window with the given height and width, position and label.
143 screen = SDL_CreateWindow ("Simplest ffmpeg player's Window",
144 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, pCodecCtx-> width,
145 pCodecCtx-> height, SDL_WINDOW_OPENGL);
146 if (! Screen)
147 {
148 fprintf (stderr, "SDL: could not create window-exiting-% s \ n", SDL_GetError ());
149 return -1;
150}
151 // Create a 2D rendering context for the window
152 sdlRender = SDL_CreateRenderer (screen, -1, 0);
153 if (! SdlRender)
154 {
155 fprintf (stderr, "SDL: cound not create render:% s \ n", SDL_GetError ());
156 return -1;
157}
158 // Create a texture for a rendering context.
159 // Create a texture for a rendering context
160 // IYUV: Y + U + V (3 planes)
161 // YV12: Y + V + U (3 planes)
162 sdlTexture = SDL_CreateTexture (sdlRender, SDL_PIXELFORMAT_IYUV,
163 SDL_TEXTUREACCESS_STREAMING, pCodecCtx-> width, pCodecCtx-> height);
164 if (! SdlTexture)
165 {
166 fprintf (stderr, "SDL: cound not create Texture:% s \ n", SDL_GetError ());
167 return -1;
168}
169 // Create a rectangular variable for later use
170 sdlRect.x = 0;
171 sdlRect.y = 0;
172 sdlRect.w = pCodecCtx-> width;
173 sdlRect.h = pCodecCtx-> height;
174 // 9, officially start reading data ************************************** *
175 while (av_read_frame (pFormatCtx, & packet)> = 0)
176 {
177 // If the read packet comes from the video stream
178 if (packet.stream_index == videoStream)
179 {
180 // Get the decoded frame from the packet
181 if (avcodec_decode_video2 (pCodecCtx, pFrame, & frameFinished, & packet) <0)
182 {
183 printf ("Decode Error! \ N");
184 return -1;
185}
186 // If it is determined to complete, get the video frame
187 if (frameFinished)
188 {
189 // Convert frame data format
190 sws_scale (img_convert_ctx, pFrame-> data, pFrame-> linesize, 0,
191 pCodecCtx-> height,
192 pFrameYUV-> data,
193 pFrameYUV-> linesize);
194 #if OUTPUT_YUV420P
195 y_size = pCodecCtx-> width * pCodecCtx-> height;
196 fwrite (pFrameYUV-> data [0], 1, y_size, fp_yuv); // Y
197 fwrite (pFrameYUV-> data [1], 1, y_size / 4, fp_yuv); // U
198 fwrite (pFrameYUV-> data [2], 1, y_size / 4, fp_yuv); // V
199 #endif
200 // SDL display ~~~~~~~~~~~~~~~
201 #if 0
202 SDL_UpdateTexture (sdlTexture, NULL, pFrameYUV-> data [0], pFrameYUV-> linesize [0]);
203 #else
204 SDL_UpdateYUVTexture (sdlTexture, & sdlRect, pFrameYUV-> data [0],
205 pFrameYUV-> linesize [0], pFrameYUV-> data [1],
206 pFrameYUV-> linesize [1], pFrameYUV-> data [2],
207 pFrameYUV-> linesize [2]);
208 #endif
209 SDL_RenderClear (sdlRender);
210 SDL_RenderCopy (sdlRender, sdlTexture, NULL, & sdlRect);
211 SDL_RenderPresent (sdlRender);
212 // End SDL ~~~~~~~~~~~~~~~
213 SDL_Delay (40); // Delay
214}
215}
216 av_free_packet (& packet); // Free the read packet
217}
218 // ************************************************ ***************************************
219 // 10. Operations such as releasing allocated memory or closing files
220 #if OUTPUT_YUV420P
221 fclose (fp_yuv);
222 #endif
223 sws_freeContext (img_convert_ctx);
224 SDL_Quit ();
225 av_free (buffer);
226 av_free (pFrame);
227 av_free (pFrameYUV);
228 avcodec_close (pCodecCtx);
229 avformat_close_input (& pFormatCtx);
230 return EXIT_SUCCESS;
231}
232
233 #ifdef _cplusplus
234}
235 #endif