ffmpeg-tutorial04分析.doc_第1页
ffmpeg-tutorial04分析.doc_第2页
ffmpeg-tutorial04分析.doc_第3页
ffmpeg-tutorial04分析.doc_第4页
ffmpeg-tutorial04分析.doc_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

在阅读ffmpeg-tutorial代码的时候,参阅了网上的一分ffmpeg-tutorial分析中文版,在此基础上理解这几分代码的原理,下面是我对tutorial04框架的梳理。/*从main()进入int main(int argc, char *argv) SDL_Event event;VideoState *is;is = av_mallocz(sizeof(VideoState);if(argc 2) fprintf(stderr, Usage: test n);exit(1);/ Register all formats and codecsav_register_all();if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) fprintf(stderr, Could not initialize SDL - %sn, SDL_GetError();exit(1);/ Make a screen to put our video#ifndef _DARWIN_screen = SDL_SetVideoMode(640, 480, 0, 0);#elsescreen = SDL_SetVideoMode(640, 480, 24, 0);#endifif(!screen) fprintf(stderr, SDL: could not set video mode - exitingn);exit(1);av_strlcpy(is-filename,argv1, sizeof(is-filename);is-pictq_mutex = SDL_CreateMutex();is-pictq_cond = SDL_CreateCond();printf(main 1n);/设置定时器,播放第一帧画面。schedule_refresh(is, 40);is-parse_tid = SDL_CreateThread(decode_thread, is);if(!is-parse_tid) av_free(is);return -1;for(;) 省略一些代码/*进入decode_thread前面都是一些基础的操作。int decode_thread(void *arg) VideoState *is = (VideoState *)arg;AVFormatContext *pFormatCtx;AVPacket pkt1, *packet = &pkt1;int video_index = -1;int audio_index = -1;int i;is-videoStream=-1;is-audioStream=-1;global_video_state = is;/ will interrupt blocking functions if we quit!url_set_interrupt_cb(decode_interrupt_cb);/ Open video fileif(av_open_input_file(&pFormatCtx, is-filename, NULL, 0, NULL)!=0)return -1; / Couldnt open fileis-pFormatCtx = pFormatCtx;/ Retrieve stream informationif(av_find_stream_info(pFormatCtx)filename, 0);/ Find the first video streamfor(i=0; inb_streams; i+) if(pFormatCtx-streamsi-codec-codec_type=CODEC_TYPE_VIDEO &video_index streamsi-codec-codec_type=CODEC_TYPE_AUDIO &audio_index = 0) stream_component_open(is, audio_index);if(video_index = 0) stream_component_open(is, video_index); if(is-videoStream audioStream filename);goto fail;/ main decode loopprintf(decode_thread 1n);for(;) if(is-quit) break;/ seek stuff goes hereif(is-audioq.size MAX_AUDIOQ_SIZE |is-videoq.size MAX_VIDEOQ_SIZE) SDL_Delay(10);continue;if(av_read_frame(is-pFormatCtx, packet) pb) = 0) SDL_Delay(100); /* no error; wait for user input */continue; else break;printf(decode_thread 2n);/ Is this a packet from the video stream?if(packet-stream_index = is-videoStream) packet_queue_put(&is-videoq, packet); else if(packet-stream_index = is-audioStream) packet_queue_put(&is-audioq, packet); else av_free_packet(packet);/* all done - wait for it */while(!is-quit) SDL_Delay(100);fail:printf(decode_thread 3n);if(1)SDL_Event event;event.type = FF_QUIT_EVENT;event.user.data1 = is;SDL_PushEvent(&event);return 0;decode_thread里打开音频流和视频流,然后进入for循环,不断读入packet,并将video和audio的packet分别存入is-videoq和is-audioq,这里来看一下打开视频流和音频流函数。/*int stream_component_open(VideoState *is, int stream_index) AVFormatContext *pFormatCtx = is-pFormatCtx;AVCodecContext *codecCtx;AVCodec *codec;SDL_AudioSpec wanted_spec, spec;if(stream_index = pFormatCtx-nb_streams) return -1;/ Get a pointer to the codec context for the video streamcodecCtx = pFormatCtx-streamsstream_index-codec;if(codecCtx-codec_type = CODEC_TYPE_AUDIO) / Set audio settings from codec infowanted_spec.freq = codecCtx-sample_rate;wanted_spec.format = AUDIO_S16SYS;wanted_spec.channels = codecCtx-channels;wanted_spec.silence = 0;wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;wanted_spec.callback = audio_callback;wanted_spec.userdata = is;if(SDL_OpenAudio(&wanted_spec, &spec) codec_id);if(!codec | (avcodec_open(codecCtx, codec) codec_type) case CODEC_TYPE_AUDIO:is-audioStream = stream_index;is-audio_st = pFormatCtx-streamsstream_index;is-audio_buf_size = 0;is-audio_buf_index = 0;memset(&is-audio_pkt, 0, sizeof(is-audio_pkt);packet_queue_init(&is-audioq);SDL_PauseAudio(0);break;case CODEC_TYPE_VIDEO:is-videoStream = stream_index;is-video_st = pFormatCtx-streamsstream_index;packet_queue_init(&is-videoq);is-video_tid = SDL_CreateThread(video_thread, is);break;default:break;如果是video,则进入video_thread,如果是audio,则进入audio_callback,这里我们来看一下video_thread,audio_callback和tutorial03是一样的。/*int video_thread(void *arg) VideoState *is = (VideoState *)arg;AVPacket pkt1, *packet = &pkt1;int len1, frameFinished;AVFrame *pFrame;pFrame = avcodec_alloc_frame();for(;) if(packet_queue_get(&is-videoq, packet, 1) video_st-codec, pFrame, &frameFinished, packet-data, packet-size);/ Did we get a video frame?if(frameFinished) if(queue_picture(is, pFrame) videoq中取邮video packet,然后调用avcodec_decode_video解码出pFrame,之后调用queue_picture将解码出的一帧图像存入videopicturetypedef struct VideoPicture SDL_Overlay *bmp;int width, height; /* source height & width */int allocated; VideoPicture;VideoPicture结构体是一个SDL_Overlay集合,每一帧图像保存在一个Overlay中,显示的时候直接覆盖。来看看queue_picture/*/int queue_picture(VideoState *is, AVFrame *pFrame) VideoPicture *vp;int dst_pix_fmt;AVPicture pict;struct SwsContext *ctx;/* wait until we have space for a new pic */SDL_LockMutex(is-pictq_mutex);while(is-pictq_size = VIDEO_PICTURE_QUEUE_SIZE &!is-quit) SDL_CondWait(is-pictq_cond, is-pictq_mutex);SDL_UnlockMutex(is-pictq_mutex);if(is-quit)return -1;/ windex is set to 0 initiallyvp = &is-pictqis-pictq_windex;/* allocate or resize the buffer! */如果vp-bmp还没有创建,则发送FF_ALLOC_EVENT创建if(!vp-bmp |vp-width != is-video_st-codec-width |vp-height != is-video_st-codec-height) SDL_Event event;vp-allocated = 0;/* we have to do it in the main thread */event.type = FF_ALLOC_EVENT;event.user.data1 = is;SDL_PushEvent(&event);/* wait until we have a picture allocated */SDL_LockMutex(is-pictq_mutex);while(!vp-allocated & !is-quit) SDL_CondWait(is-pictq_cond, is-pictq_mutex);SDL_UnlockMutex(is-pictq_mutex);if(is-quit) return -1;/* We have a place to put our picture on the queue */ctx = sws_getContext(is-video_st-codec-width, is-video_st-codec-height,is-video_st-codec-pix_fmt,is-video_st-codec-width, is-video_st-codec-height,PIX_FMT_YUV420P,SWS_BICUBIC, NULL, NULL, NULL);if(vp-bmp) SDL_LockYUVOverlay(vp-bmp);/写入数据到SDL_Overlay中dst_pix_fmt = PIX_FMT_YUV420P;/* point pict at the queue */pict.data0 = vp-bmp-pixels0;pict.data1 = vp-bmp-pixels2;pict.data2 = vp-bmp-pixels1;pict.linesize0 = vp-bmp-pitches0;pict.linesize1 = vp-bmp-pitches2;pict.linesize2 = vp-bmp-pitches1;/ Convert the image into YUV format that SDL uses/img_convert(&pict, dst_pix_fmt,/(AVPicture *)pFrame, is-video_st-codec-pix_fmt, /is-video_st-codec-width, is-video_st-codec-height);sws_scale(ctx, pFrame-data, pFrame-linesize, 0, is-video_st-codec-height,pict.data, pict.linesize);SDL_UnlockYUVOverlay(vp-bmp);/* now we inform our display thread that we have a pic ready */if(+is-pictq_windex = VIDEO_PICTURE_QUEUE_SIZE) is-pictq_windex = 0;SDL_LockMutex(is-pictq_mutex);is-pictq_size+;SDL_UnlockMutex(is-pictq_mutex);return 0;这里发送了一个FF_ALLOC_EVENT消息,在main函数中截获这个消息后调用my_alloc_picture创建一个SDL_Overlayvoid my_alloc_picture(void *userdata) VideoState *is = (VideoState *)userdata;VideoPicture *vp;vp = &is-pictqis-pictq_windex;if(vp-bmp) / we already have one make another, bigger/smallerSDL_FreeYUVOverlay(vp-bmp);/ Allocate a place to put our YUV image on that screenvp-bmp = SDL_CreateYUVOverlay(is-video_st-codec-width,is-video_st-codec-height,SDL_YV12_OVERLAY,screen);vp-width = is-video_st-codec-width;vp-height = is-video_st-codec-height;SDL_LockMutex(is-pictq_mutex);vp-allocated = 1;SDL_CondSignal(is-pictq_cond);SDL_UnlockMutex(is-pictq_mutex);我们回过头来看看main函数/*int main(int argc, char *argv) schedule_refresh(is, 40);for(;) printf(main 2n);SDL_WaitEvent(&event);switch(event.type) case FF_QUIT_EVENT:case SDL_QUIT:is-quit = 1;SDL_Quit();return 0;break;case FF_ALLOC_EVENT:my_alloc_picture(event.user.data1);break;case FF_REFRESH_EVENT:video_refresh_timer(event.user.data1);break;default:break;一开始进入main时就调用了schedule_refresh(is, 40);/*static void schedule_refresh(VideoState *is, int delay) printf(schedule_refreshn);SDL_AddTimer(delay, sdl_refresh_timer_cb, is);/*static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque) SDL_Event event;event.type = FF_REFRESH_EVENT;event.user.data1 = opaque;SDL_PushEvent(&event);printf(sdl_refresh_timer_cbn);return 0; /* 0 means stop timer */我们可以看到,调用schedule_refresh- sdl_refresh_timer_cb发送FF_REFRESH_EVENT显示一个SDL_Overlay,即显示一幅图像。/*void video_refresh_timer(void *userdata) VideoState *is = (V

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论