Statement: copyright belongs to the great god dranger, reference address: http://dranger.com/ffmpeg/tutorial01.html, I just changed the tutorial is not applicable to 0.7 FFMPEG API code to be able to compile and run in 0.7 FFMPEG program,
The compiling environment is centos 5.9, FFMPEG version: 0.7.15, and x264 version: 20110627.
The Code is as follows:
// 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 <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libswscale/swscale.h>#include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #include <SDL/SDL.h> static int sws_flags = SWS_BICUBIC;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
Makefile is
all: ffmpeg_test ffplayCXX=gccCXXFLAGS=-c -g -O0 -fPIC -I/usr/local/include -L/usr/local/lib LIBS=-lavcodec -lavutil -lavfilter -lavformat -lavdevice -lswscale -lpthread -L/usr/local/lib.c.o:$(CXX) $(CXXFLAGS) $<ffmpeg_test:ffmpeg.cppg++ -g -O0 -fPIC -I/usr/local/include -o $@ $^ $(LIBS) ffplay:ffplay.cppg++ -g -O0 -fPIC -I/usr/local/include -o $@ $^ $(LIBS)tutorial01:tutorial01.cgcc -g -O0 -fPIC -I/usr/lcoal/include -o $@ $^ $(LIBS)clean:rm -f *.orm -f *~rm -f ffmpeg_testrm -f ffplayrm -f *.ppmrm -f tutotrial01
Compile make tutorial01
Run as./tutorial01 input. Avi
If no error occurs, five images can be generated.
I want to retrieve the frame and save it as a BMP image. I am too lazy. I just wrote the header of the BMP file and wrote the pframe-> data [0] content, the content of the final BMP image is the opposite of the upper and lower. The Code is as follows, which only changes the saveframe function of the stored image:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <SDL/SDL.h>#include <libavformat/avformat.h>#include <libswscale/swscale.h>#include <libavcodec/avcodec.h>#pragma pack (1)typedef struct BITMAPFILEHEADER{ short bfType; int bfSize; short bfReserved1; short bfReserved2; int bfOffBits;} BITMAPFILEHEADER;#pragma pack ()typedef struct BITMAPINFOHEADER{ int biSize; long biWidth; long biHeight; short biPlanes; short biBitCount; int biCompression; int biSizeImage; long biXPelsPerMeter; long biYPelsPerMeter; int biClrUsed; int biClrImportant;} BITMAPINFOHEADER;void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) { FILE *pFile; char szFilename[32]; int y; struct BITMAPFILEHEADER bfh; struct BITMAPINFOHEADER bih; // Open file sprintf(szFilename, "frame%d.bmp", iFrame); pFile=fopen(szFilename, "wb"); if(pFile==NULL) return; bfh.bfType = 0x4D42; bfh.bfSize = 14 + 40 + width * height; bfh.bfOffBits = 14 + 40; bfh.bfReserved1 = 0; bfh.bfReserved2 = 0; fwrite (&bfh, 14, 1, pFile);//write the bmp header 'BM'(ASCII:0x4D42). bih.biBitCount = 24; bih.biWidth = width; bih.biHeight = height; bih.biSizeImage = width * height *3; bih.biClrImportant = 0; bih.biClrUsed = 0; bih.biCompression = 0; bih.biPlanes = 1; bih.biSize = 40; bih.biXPelsPerMeter = 0; bih.biYPelsPerMeter = 0; fwrite (&bih, 40, 1, pFile);//write the bit map info header. fwrite ( pFrame->data[0] , width * height *3 , 1, pFile); // Close file fclose(pFile);}int main(int argc, char *argv[]){AVFormatContext *pFormatCtx;int i,videoStream;AVCodecContext *pCodecCtx;AVCodec*pCodec;AVFrame*pFrame;AVFrame *pFrameRGB;AVPacket packet;int numBytes;uint8_t *buffer;int frameFinished;if(argc < 2){printf("please open a movie file\n");exit(0);}av_register_all();if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL) != 0){printf("error to open the file\n");exit(0);}if(av_find_stream_info(pFormatCtx) < 0){printf("error to find the stream info of the file\n");exit(0);}dump_format(pFormatCtx, 0, argv[1], 0); videoStream = -1;for(i=0; i < pFormatCtx->nb_streams; i++)if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO){videoStream = i;break;}if(videoStream == -1){printf("unsupported File format\n");exit(0);}pCodecCtx = pFormatCtx->streams[videoStream]->codec;pCodec=avcodec_find_decoder(pCodecCtx->codec_id);if(pCodec == NULL){fprintf(stderr, "Unsupported codec\n");exit(0);}if(avcodec_open(pCodecCtx, pCodec) < 0){printf("error to open codec\n");exit(0);}pFrame = avcodec_alloc_frame();pFrameRGB = avcodec_alloc_frame();if(pFrameRGB == NULL){printf("unable to alloc memory for pFrameRGB\n");exit(0);}numBytes= avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);buffer= (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);static struct SwsContext *img_convert_ctx;if(img_convert_ctx == NULL){img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height,PIX_FMT_RGB24,SWS_BICUBIC,NULL,NULL,NULL);if(img_convert_ctx == NULL){printf("error to initialize the conversion context \n");exit(0);}}i = 0;while(av_read_frame(pFormatCtx, &packet) >= 0){if(packet.stream_index == videoStream){avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size);if(frameFinished){sws_scale(img_convert_ctx, (const uint8_t* const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);if(++i <= 5)SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);}}av_free_packet(&packet);}av_free(buffer);av_free(pFrameRGB);av_free(pFrame);avcodec_close(pCodecCtx);av_close_input_file(pFormatCtx);return 0;}