diff --git a/get_and_display_frames.c b/get_and_display_frames.c new file mode 100644 index 0000000..5a09958 --- /dev/null +++ b/get_and_display_frames.c @@ -0,0 +1,183 @@ +#include +#include +#include + +#include +#include + +#ifdef __MINGW32__ +#undef main /* Prevents SDL from overriding main() */ +#endif + +#include + +int main(int argc, char *argv[]) { + AVFormatContext *pFormatCtx = NULL; + int i, videoStream; + AVCodecContext *pCodecCtx = NULL; + AVCodec *pCodec = NULL; + AVFrame *pFrame = NULL; + AVPacket packet; + int frameFinished; + //float aspect_ratio; + + AVDictionary *optionsDict = NULL; + struct SwsContext *sws_ctx = NULL; + + SDL_Overlay *bmp = NULL; + SDL_Surface *screen = NULL; + SDL_Rect rect; + SDL_Event event; + + 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); + } + + // Open video file + if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0) + return -1; // Couldn't open file + + // Retrieve stream information + if(avformat_find_stream_info(pFormatCtx, NULL)<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; inb_streams; i++) + if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_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_open2(pCodecCtx, pCodec, &optionsDict)<0) + return -1; // Could not open codec + + // Allocate video frame + pFrame=av_frame_alloc(); + + // Make a screen to put our video +#ifndef __DARWIN__ + screen = SDL_SetVideoMode(pCodecCtx->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); + + sws_ctx = + sws_getContext + ( + pCodecCtx->width, + pCodecCtx->height, + pCodecCtx->pix_fmt, + pCodecCtx->width, + pCodecCtx->height, + PIX_FMT_YUV420P, + SWS_BILINEAR, + 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 + avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, + &packet); + + // 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]; + + // Convert the image into YUV format that SDL uses + sws_scale + ( + sws_ctx, + (uint8_t const * const *)pFrame->data, + pFrame->linesize, + 0, + pCodecCtx->height, + pict.data, + pict.linesize + ); + + 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); + + // Close the video file + avformat_close_input(&pFormatCtx); + + return 0; +}