[Libav-user] ffmpeg and SDL2.0

David martin vilanew at gmail.com
Mon Mar 12 15:27:11 CET 2012


Hi,
I'm working on the use of ffmpeg with SDL2.0. Since i'm pretty new with 
both i'm moving slowly....

Here is the code that is compiling and running, although the image is 
not properly displayed for some reason that i don't know. i was 
wondering if you could run it on your machines and let me know what the 
image is not displayed.
You can copy the whole code and run it. For some reason the renderer 
does not display the image. I would appreciate if somebody could have a 
look as it is almost done. Note that the code is not optimized yet, just 
wanted to have a functional code first...

Any help would be great !!!
thanks

Runit with a mpeg video for example like:
./test2 file.mpeg


/*
  * test2.c
  *
  *  Created on: Mar 9, 2012
  *      Author: dvi
  */
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <SDL.h>
#include <stdio.h>

void sdl_init(AVFormatContext* format_context, AVCodecContext* 
codec_context, int videostream ) {
     SDL_Init(SDL_INIT_EVERYTHING);
	AVFrame* frame;
	AVFrame *pFrameRGB;
	AVPacket avpacket;
	AVPicture  picture;


     // Convert the image from its native format to RGB
     struct SwsContext *img_convert_ctx =NULL;

     SDL_Event event;
     SDL_RendererInfo info;
     SDL_Texture *texture;
     SDL_Surface *image;
     Uint32 then, now , frames;
     int w = 640;
     int h = 480;
     int done = 0;
     SDL_Window * window = SDL_CreateWindow("SDL", 
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, 0);
     SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);

     SDL_GetRendererInfo(renderer, &info);
     printf("Using %s rendering\n", info.name);



     SDL_Log("+++++ INIT DONE +++++");


     frame = avcodec_alloc_frame();

     pFrameRGB = avcodec_alloc_frame();
         if (pFrameRGB == NULL)
         {
          printf("Cannot allocate pFrame\n");
          exit(-1);
         }

         unsigned char* pixels;
         int pitch;
         uint8_t *buffer;
         int numBytes;
         // Determine required buffer size and allocate buffer
         numBytes=avpicture_get_size(PIX_FMT_RGB24, codec_context->width,
         		codec_context->height);
         buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));


         // Assign appropriate parts of buffer to image planes in pFrameRGB
         // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
         // of AVPicture
         avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
         		codec_context->width, codec_context->height);

         while (av_read_frame(format_context, &avpacket) >= 0) {
         	if (avpacket.stream_index == videostream) {
         		// Video stream packet
         		int frame_finished;

         		avcodec_decode_video2(codec_context, frame, &frame_finished, 
&avpacket);

         		if(frame_finished)
         		{

         			picture.data[0] = frame->data[0];
         			picture.data[1] = frame->data[1];
         			picture.data[2] = frame->data[2];
         			picture.linesize[0] = frame->linesize[0];
         			picture.linesize[1] = frame->linesize[1];
         			picture.linesize[2] = frame->linesize[2];



         			img_convert_ctx  = sws_getCachedContext(img_convert_ctx,
         					codec_context->width,
         					codec_context->height,
         					//PIX_FMT_RGB24,
         					PIX_FMT_YUV420P,
         					frame->width,
         					frame->height,
         					PIX_FMT_RGB24,
         					SWS_BICUBIC,
         					NULL,
         					NULL,
         					NULL);


         			if (img_convert_ctx == NULL)
         			{
         				fprintf(stderr, "Cannot initialize the conversion context!\n");
         				exit(1);
         			}



         			int s = sws_scale(
         					img_convert_ctx,
         					frame->data,
         					frame->linesize,
         					0,
         					codec_context->height,
         					picture.data,
         					picture.linesize);


         			texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, 
SDL_TEXTUREACCESS_STREAMING, codec_context->width, 
codec_context->height);//3 plane texture

         			if (!texture) {
         				fprintf(stderr, "Couldn't set create texture: %s\n", 
SDL_GetError());
         				exit(-1);
         			}


							if(texture && !SDL_LockTexture(texture, NULL, (void **)&pixels, 
&pitch) ) {

								if(pitch == picture.linesize[0]) {
									int size = pitch * frame->height;
									memcpy(pixels, picture.data[0], size);
									memcpy(pixels + size, picture.data[2], size / 4);
									memcpy(pixels + size * 5 / 4, picture.data[1], size / 4);
								}


								else {
									register unsigned char *y1,*y2,*y3,*i1,*i2,*i3;
									int i;
									y1 = pixels;
									y3 = pixels + pitch * frame->height;
									y2 = pixels + pitch * frame->height * 5 / 4;

									i1=picture.data[0];
									i2=picture.data[1];
									i3=picture.data[2];

									for (i = 0; i<(frame->height/2); i++) {
										memcpy(y1,i1,pitch);
										i1+=picture.linesize[0];
										y1+=pitch;
										memcpy(y1,i1,pitch);

										memcpy(y2,i2,pitch / 2);
										memcpy(y3,i3,pitch / 2);

										y1+=pitch;
										y2+=pitch / 2;
										y3+=pitch / 2;
										i1+=picture.linesize[0];
										i2+=picture.linesize[1];
										i3+=picture.linesize[2];
									}
								}
							}//texture
							SDL_UnlockTexture(texture);
         		}//frame
         av_free_packet(&avpacket);

         	}//avpacket

     //while (!done) {
     	SDL_PollEvent(&event);

     	 switch(event.type) {

                if (event.key.keysym.sym == SDLK_ESCAPE) {
                 done = 1;
                }
                break;

            case SDL_QUIT:
            	//done=1;
             SDL_Log("Unhandled event type=%d", event.type);
             done=1;
             break;
     	 }
     	 /* Print out some timing information */
     	  //  printf("TIMING %d\n",avpacket.dts);
     	 //SDL_UpdateTexture(texture, NULL, imageYUV, image->w)
         if (!SDL_UpdateTexture(texture, NULL, frame, frame->width)) {
             //SDL_UpdateTexture(texture, NULL, imageYUV, image->w);

                 fprintf(stderr, "Couldn't  update texture: %s\n", 
SDL_GetError());
                 //exit(-1);
             }

         SDL_RenderClear(renderer);
         SDL_RenderCopy(renderer, texture, NULL, NULL);
         SDL_RenderPresent(renderer);
         SDL_Delay(20);
     //}

//        		}

      }//while av_read_frame

     SDL_Log("+++++ FINISHED +++++");
     SDL_Quit();
}


int main(int argc, char * argv[]) {

	AVCodecContext* codec_context;
	int videostream;

	if (argc < 2) {
			printf("Usage: %s filename\n", argv[0]);
			return 0;
		}

		// Register all available file formats and codecs
		av_register_all();

		int err;
		// Init SDL with video support
		err = SDL_Init(SDL_INIT_VIDEO);
		if (err < 0) {
			fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
			return -1;
		}

		// Open video file
		const char* filename = argv[1];
		AVFormatContext* format_context = NULL;
		err = avformat_open_input(&format_context, filename, NULL, NULL);
		if (err < 0) {
			fprintf(stderr, "ffmpeg: Unable to open input\n");
			return -1;
		}

		// Retrieve stream information
		err = avformat_find_stream_info(format_context, NULL);
		if (err < 0) {
			fprintf(stderr, "ffmpeg: Unable to find stream info\n");
			return -1;
		}

		// Dump information about file onto standard error
		av_dump_format(format_context, 0, argv[1], 0);

		// Find the first video stream

		for (videostream = 0; videostream < format_context->nb_streams; 
++videostream) {
			if (format_context->streams[videostream]->codec->codec_type == 
AVMEDIA_TYPE_VIDEO) {
				break;
			}
		}
		if (videostream == format_context->nb_streams) {
			fprintf(stderr, "ffmpeg: Unable to find video stream\n");
			return -1;
		}

		codec_context = format_context->streams[videostream]->codec;
		AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);

		avcodec_alloc_context3(codec);


		 if (avcodec_open2(codec_context, codec, NULL) < 0)
		 {
			 fprintf(stderr, "ffmpeg: Unable to allocate codec context\n");
		 }

			else {
				printf("Codec initialized\n");

		}

		 /*
		 Initializing display
		 */
		 printf("Width:%d\n",codec_context->width);
		 printf("height:%d\n",codec_context->height);
		 //exit(0);


     sdl_init(format_context, codec_context,videostream);


     return 0;
}



More information about the Libav-user mailing list