设为首页 收藏本站
查看: 965|回复: 0

[经验分享] H.264:FFMpeg 实现简单的播放器

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-1-14 10:26:32 | 显示全部楼层 |阅读模式
FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手。我刚接触FFMPEG的时候也感觉不知从何学起。

因此我把自己做项目过程中实现的一个非常简单的视频播放器(大约100行代码)源代码传上来,以作备忘,同时方便新手学习FFMPEG。

该播放器虽然简单,但是几乎包含了使用FFMPEG播放一个视频所有必备的API,并且使用SDL显示解码出来的视频。

并且支持流媒体等多种视频输入,处于简单考虑,没有音频部分,同时视频播放采用直接延时40ms的方式

平台使用VC2010

使用了最新的FFMPEG类库

直接贴代码

int _tmain(int argc, _TCHAR* argv[])
{
       AVFormatContext        *pFormatCtx;
       int i, videoindex;
       AVCodecContext        *pCodecCtx;
       AVCodec                        *pCodec;
       char filepath[]="nwn.mp4";
       av_register_all();
       avformat_network_init();
       pFormatCtx = avformat_alloc_context();
       if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){
               printf("无法打开文件\n");
               return -1;
       }
       if(av_find_stream_info(pFormatCtx)<0)
       {
               printf("Couldn't find stream information.\n");
               return -1;
       }
       videoindex=-1;
       for(i=0; i<pFormatCtx->nb_streams; i++)
               if(pFormatCtx->streams->codec->codec_type==AVMEDIA_TYPE_VIDEO)
               {
                       videoindex=i;
                       break;
               }
               if(videoindex==-1)
               {
                       printf("Didn't find a video stream.\n");
                       return -1;
               }
               pCodecCtx=pFormatCtx->streams[videoindex]->codec;
               pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
               if(pCodec==NULL)
               {
                       printf("Codec not found.\n");
                       return -1;
               }
               if(avcodec_open(pCodecCtx, pCodec)<0)
               {
                       printf("Could not open codec.\n");
                       return -1;
               }
               AVFrame        *pFrame,*pFrameYUV;
               pFrame=avcodec_alloc_frame();
               pFrameYUV=avcodec_alloc_frame();
               uint8_t *out_buffer;
               out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)];
               avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
       //------------SDL----------------
               if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {  
                       printf( "Could not initialize SDL - %s\n", SDL_GetError());
                       exit(1);
               }
               SDL_Surface *screen;
               screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
               if(!screen) {  printf("SDL: could not set video mode - exiting\n");  
               exit(1);
               }
               SDL_Overlay *bmp;
               bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,SDL_YV12_OVERLAY, screen);
               SDL_Rect rect;
       //---------------
               int ret, got_picture;
               static struct SwsContext *img_convert_ctx;
               int y_size = pCodecCtx->width * pCodecCtx->height;

               AVPacket *packet=(AVPacket *)malloc(sizeof(AVPacket));
               av_new_packet(packet, y_size);
               //输出一下信息-----------------------------
               printf("文件信息-----------------------------------------\n");
               av_dump_format(pFormatCtx,0,filepath,0);
               printf("-------------------------------------------------\n");
               //------------------------------
               while(av_read_frame(pFormatCtx, packet)>=0)
               {
                       if(packet->stream_index==videoindex)
                       {
                               ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
                               if(ret < 0)
                               {
                                       printf("解码错误\n");
                                       return -1;
                               }
                               if(got_picture)
                               {
                                       img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P,   SWS_BICUBIC, NULL, NULL, NULL);
                                       sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);

                                       SDL_LockYUVOverlay(bmp);
                                       bmp->pixels[0]=pFrameYUV->data[0];
                                       bmp->pixels[2]=pFrameYUV->data[1];
                                       bmp->pixels[1]=pFrameYUV->data[2];     
                                       bmp->pitches[0]=pFrameYUV->linesize[0];
                                       bmp->pitches[2]=pFrameYUV->linesize[1];   
                                       bmp->pitches[1]=pFrameYUV->linesize[2];
                                       SDL_UnlockYUVOverlay(bmp);
                                       rect.x = 0;   
                                       rect.y = 0;   
                                       rect.w = pCodecCtx->width;   
                                       rect.h = pCodecCtx->height;   
                                       SDL_DisplayYUVOverlay(bmp, &rect);
                                       //延时40ms
                                       SDL_Delay(40);
                               }
                       }
                       av_free_packet(packet);
               }
               delete[] out_buffer;
               av_free(pFrameYUV);
               avcodec_close(pCodecCtx);
               avformat_close_input(&pFormatCtx);

               return 0;
       }

完整工程下载地址:
金山快盘附件ffmpeg_simple_player.7z(7.91MB)



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-14211-1-1.html 上篇帖子: Linux下添加硬盘,分区,格式化详解 下篇帖子: LDAP查询结果按照指定的属性排序 播放器
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表