2013年2月3日 星期日

FFMEPG -- A ffmpeg and SDL Tutorial : tutorial02

參考 http://dranger.com/ffmpeg/tutorial02.html 進行實作練習,以下附上一個可以在 ffmpeg 1.1.1 (build Jan 27 2013) 正確編譯的例子。



// tutorial02.c // A pedagogical video player that will stream through every video frame as fast as it can. // // Code based on FFplay, Copyright (c) 2003 Fabrice Bellard, // and a tutorial by Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de) // Tested on Gentoo, CVS version 5/01/07 compiled with GCC 4.1.1 // Use // // gcc -o tutorial02 tutorial02.c -lavformat -lavcodec -lz -lm `sdl-config --cflags --libs` // to build (assuming libavformat and libavcodec are correctly installed, // and assuming you have sdl-config. Please refer to SDL docs for your installation.) // // Run using // tutorial02 myvideofile.mpg // // to play the video stream on your screen. // 201302023 albert.liao modified start //#include //#include //#include //#include #include #include #include #include #include //#undef main /* Prevents SDL from overriding main() */ // 201302023 albert.liao modified end #ifdef __MINGW32__ //#undef main /* Prevents SDL from overriding main() */ #endif #include int main(int argc, char *argv[]) { AVFormatContext *pFormatCtx; int i, videoStream; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame; AVPacket packet; int frameFinished; float aspect_ratio; SDL_Overlay *bmp; SDL_Surface *screen; SDL_Rect rect; SDL_Event event; // 201302023 albert.liao modified start static struct SwsContext *img_convert_ctx; // 201302023 albert.liao modified end if(argc < 2) { fprintf(stderr, "Usage: test \n"); exit(1); } // Register all formats and codecs av_register_all(); if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); exit(1); } // 201302023 albert.liao modified start // Open video file //if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0) pFormatCtx = avformat_alloc_context(); if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0) return -1; // Couldn't open file // 201302023 albert.liao modified end // Retrieve stream information // 201302023 albert.liao modified start //if(av_find_stream_info(pFormatCtx)<0 data-blogger-escaped--1="" data-blogger-escaped-0="" data-blogger-escaped-201302023="" data-blogger-escaped-about="" data-blogger-escaped-albert.liao="" data-blogger-escaped-argv="" data-blogger-escaped-av_dump_format="" data-blogger-escaped-avformat_find_stream_info="" data-blogger-escaped-couldn="" data-blogger-escaped-dump="" data-blogger-escaped-dump_format="" data-blogger-escaped-end="" data-blogger-escaped-error="" data-blogger-escaped-file="" data-blogger-escaped-find="" data-blogger-escaped-first="" data-blogger-escaped-for="" data-blogger-escaped-i="" data-blogger-escaped-if="" data-blogger-escaped-information="" data-blogger-escaped-modified="" data-blogger-escaped-onto="" data-blogger-escaped-pformatctx-="" data-blogger-escaped-pformatctx="" data-blogger-escaped-return="" data-blogger-escaped-standard="" data-blogger-escaped-stream="" data-blogger-escaped-t="" data-blogger-escaped-the="" data-blogger-escaped-video="" data-blogger-escaped-videostream="-1;">nb_streams; i++) // 201302023 albert.liao modified start //if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) { // 201302023 albert.liao modified end 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 } // 201302023 albert.liao modified start // Open codec //if(avcodec_open(pCodecCtx, pCodec)<0 data-blogger-escaped--1="" data-blogger-escaped-201302023="" data-blogger-escaped-__darwin__="" data-blogger-escaped-a="" data-blogger-escaped-albert.liao="" data-blogger-escaped-allocate="" data-blogger-escaped-avcodec_open2="" data-blogger-escaped-codec="" data-blogger-escaped-could="" data-blogger-escaped-end="" data-blogger-escaped-frame="" data-blogger-escaped-if="" data-blogger-escaped-ifndef="" data-blogger-escaped-make="" data-blogger-escaped-modified="" data-blogger-escaped-not="" data-blogger-escaped-null="" data-blogger-escaped-open="" data-blogger-escaped-our="" data-blogger-escaped-pcodec="" data-blogger-escaped-pcodecctx="" data-blogger-escaped-pframe="avcodec_alloc_frame();" data-blogger-escaped-put="" data-blogger-escaped-return="" data-blogger-escaped-screen="SDL_SetVideoMode(pCodecCtx-" data-blogger-escaped-to="" data-blogger-escaped-video="">width, pCodecCtx->height, 0, 0); #else screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0); #endif if(!screen) { fprintf(stderr, "SDL: could not set video mode - exiting\n"); exit(1); } // Allocate a place to put our YUV image on that screen bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen); // 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) { // 201302023 albert.liao modified start // Decode video frame // avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size); avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); // 201302023 albert.liao modified end // Did we get a video frame? if(frameFinished) { SDL_LockYUVOverlay(bmp); AVPicture pict; pict.data[0] = bmp->pixels[0]; pict.data[1] = bmp->pixels[2]; pict.data[2] = bmp->pixels[1]; pict.linesize[0] = bmp->pitches[0]; pict.linesize[1] = bmp->pitches[2]; pict.linesize[2] = bmp->pitches[1]; // 201302023 albert.liao modified start // Convert the image into YUV format that SDL uses //img_convert(&pict, PIX_FMT_YUV420P, // (AVPicture *)pFrame, pCodecCtx->pix_fmt, // pCodecCtx->width, pCodecCtx->height); img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,\ pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,\ PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL); // other codes // Convert the image from its native format to RGB sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize,\ 0, pCodecCtx->height, pict.data, pict.linesize); // 201302023 albert.liao modified end SDL_UnlockYUVOverlay(bmp); rect.x = 0; rect.y = 0; rect.w = pCodecCtx->width; rect.h = pCodecCtx->height; SDL_DisplayYUVOverlay(bmp, &rect); } } // Free the packet that was allocated by av_read_frame av_free_packet(&packet); SDL_PollEvent(&event); switch(event.type) { case SDL_QUIT: SDL_Quit(); exit(0); break; default: break; } } // Free the YUV frame av_free(pFrame); // Close the codec avcodec_close(pCodecCtx); // 201302023 albert.liao modified start // Close the video file // av_close_input_file(pFormatCtx); avformat_close_input(&pFormatCtx); // 201302023 albert.liao modified end return 0; }