I've been doing a lot of ffmpeg programming lately and have been finding it extremely painful. There just isn't much for help out there, certainly no real documentation for using the viatal avcodec library.
'dranger' has about the only comprehensive tutorial around and it's showing its age at this point. There's a few newer notes about updating it, but even those don't cover the latest libavcodec API changes. So I figured I would throw out my version of the first tutorial file, tutorial01.c. The most important change is replacing the long excised img_convert call with the sws_scale call (which also requires creating the SwsContext object). I also just tweaked a couple of the calls to remove any deprecated API calls.
Have at it!
You can build it with the following command:
'dranger' has about the only comprehensive tutorial around and it's showing its age at this point. There's a few newer notes about updating it, but even those don't cover the latest libavcodec API changes. So I figured I would throw out my version of the first tutorial file, tutorial01.c. The most important change is replacing the long excised img_convert call with the sws_scale call (which also requires creating the SwsContext object). I also just tweaked a couple of the calls to remove any deprecated API calls.
Have at it!
You can build it with the following command:
$ gcc -o tutorial01 tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lswscale -lzDownload it here: tutorial01.c
// tutorial01.c // Code based on a tutorial by Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de) // Tested on Gentoo, CVS version 5/01/07 compiled with GCC 4.1.1 // A small sample program that shows how to use libavformat and libavcodec to // read video from a file. // // Use // // gcc -o tutorial01 tutorial01.c -lavformat -lavcodec -lz // // to build (assuming libavformat and libavcodec are correctly installed // your system). // // Run using // // tutorial01 myvideofile.mpg // // to write the first five frames from "myvideofile.mpg" to disk in PPM // format. #include#include #include #include void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) { FILE *pFile; char szFilename[32]; int y; // Open file sprintf(szFilename, "frame%d.ppm", iFrame); pFile=fopen(szFilename, "wb"); if(pFile==NULL) return; // Write header fprintf(pFile, "P6\n%d %d\n255\n", width, height); // Write pixel data for(y=0; y data[0]+y*pFrame->linesize[0], 1, width*3, pFile); // Close file fclose(pFile); } int main(int argc, char *argv[]) { AVFormatContext *pFormatCtx=NULL; int i, videoStream; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame; AVFrame *pFrameRGB; AVPacket packet; int frameFinished; int numBytes; uint8_t *buffer; struct SwsContext *img_convert_ctx; int frameCount=0; if(argc < 2) { printf("Please provide a movie file\n"); return -1; } // Register all formats and codecs av_register_all(); // Open video file if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0) return -1; // Couldn't open file // Retrieve stream information if(av_find_stream_info(pFormatCtx)<0) return -1; // Couldn't find stream information // Dump information about file onto standard error av_dump_format(pFormatCtx, 0, argv[1], 0); // Find the first video stream videoStream=-1; for(i=0; i nb_streams; i++) if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { videoStream=i; break; } if(videoStream==-1) return -1; // Didn't find a video stream // Get a pointer to the codec context for the video stream pCodecCtx=pFormatCtx->streams[videoStream]->codec; // Find the decoder for the video stream pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL) { fprintf(stderr, "Unsupported codec!\n"); return -1; // Codec not found } // Open codec if(avcodec_open(pCodecCtx, pCodec)<0) return -1; // Could not open codec // Allocate video frame pFrame=avcodec_alloc_frame(); // Allocate an AVFrame structure pFrameRGB=avcodec_alloc_frame(); if(pFrameRGB==NULL) return -1; // Determine required buffer size and allocate buffer numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->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, pCodecCtx->width, pCodecCtx->height); int w = pCodecCtx->width; int h = pCodecCtx->height; img_convert_ctx = sws_getContext( w, h, pCodecCtx->pix_fmt, w, h, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); // Read frames and save first five frames to disk i=0; while(av_read_frame(pFormatCtx, &packet)>=0) { // Is this a packet from the video stream? if(packet.stream_index==videoStream) { // Decode video frame int len = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); if ( len < 0 ) { fprintf(stderr, "Problems decoding frame\n"); return 1; } fprintf(stderr, "len = %d\n", len ); // Did we get a video frame? if(frameFinished) { ++frameCount; fprintf(stderr, "Saving frame %d\n", frameCount); #if 0 // this is the old code img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); #else sws_scale( img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); #endif // Save the frame to disk if(++i<=5) SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i); } } // Free the packet that was allocated by av_read_frame av_free_packet(&packet); } // Free the RGB image av_free(buffer); av_free(pFrameRGB); // Free the YUV frame av_free(pFrame); // Close the codec avcodec_close(pCodecCtx); // Close the video file av_close_input_file(pFormatCtx); return 0; }


