经过网络传输接收到的码流,已经存放在公共链表 PacketNode_t 中,码流经过解码成YUV或RGB后才能播放,接下来就介绍FFmpeg解码过程和 SDL 播放视频。

FFmpeg 解码

码流解码很消耗CPU资源,所以要单独开解码线程,在这之前应该进行解码器的初始化。

解码器初始化

AVFrame *m_picture;
AVFrame *m_pFrameYUV;
AVCodec *m_codec;
AVCodecContext *m_pCodecCtx;
struct SwsContext *m_pImgCtx;
AVCodecParserContext *m_pCodecParserCtx;
AVFormatContext *m_pFmtCtx;
int      m_PicBytes;
uint8_t* m_PicBuf;BOOL CVideoDlg::InitDecoder()
{int Ret = 0;av_register_all();        //注册所有解码器m_pFmtCtx = avformat_alloc_context(); if (NULL == m_pFmtCtx){Printf("avformat_alloc_context failed!\n");}//寻找解码器m_codec = avcodec_find_decoder(CODEC_ID_H265);if (!m_codec){Printf(TRUE,FALSE,"Codec not found !\n");return 0;}//解码器结构m_pCodecCtx = avcodec_alloc_context3(m_codec);m_pCodecParserCtx = av_parser_init(AV_CODEC_ID_H264);if (!m_pCodecParserCtx){Printf(TRUE,FALSE,"Could not allocate video parser context\n");return 0;}//打开解码器Ret = avcodec_open2(m_pCodecCtx, m_codec, NULL);if (Ret < 0){Printf(TRUE,FALSE,"Could not open codec !\n");return 0;}//AVFrame分配空间m_picture = av_frame_alloc();m_pFrameYUV = av_frame_alloc();m_PicBytes = 0;m_PicBuf = NULL;m_pImgCtx = NULL;if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {AfxMessageBox(_T("Could not initialize SDL\n"));return 0;}return TRUE;
}

解码线程

在初始化过程中,已经通过定时器 SetTimer() 实现解码线程的声明:

void CVideoDlg::OnTimer(UINT_PTR nIDEvent)
{if (0 == thread_exit){return;}if(123 == nIDEvent){pThreadPlay = AfxBeginThread(Thread_Play,this); //开启线程KillTimer(123);}
}

Thread_Play就是解码线程函数的地址,接下来去实现这个函数:

static UINT Thread_Play(VOID *pVoid)
{CVideoDlg *pDlg = (CVideoDlg*) pVoid;   //指针绑定对话框类pDlg->FFmpegPlayer();                  //FFmpeg解码并播放return 0;
}void CVideoDlg::FFmpegPlayer()
{int Ret = 0;int64_t pos = 0;int vid_idx,i;AVPacket pkt;av_init_packet(&pkt);//判断视频for( i = 0; i < m_pFmtCtx->nb_streams; i++){if(m_pFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){vid_idx = i;}}//显示在MFC控件上screen_w = g_width;screen_h = g_height;screen = SDL_CreateWindowFrom(GetDlgItem(IDC_SCREEN)->GetSafeHwnd());if (!screen) {AfxMessageBox(_T("SDL: could not create window - exiting\n"));return ;}sdlRenderer = SDL_CreateRenderer(screen, -1, 0);sdlTexture  = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, screen_w, screen_h);sdlRect.x = 0;sdlRect.y = 0;sdlRect.w = screen_w;sdlRect.h = screen_h;while (1){SDL_WaitEvent(&g_event);if (g_event.type != SFM_BREAK_EVENT)  /{if (!packetList.empty()){//将码流数据复制到AvPacket中cs.Lock();pkt.size  = packetList.front().length;pkt.data  = packetList.front().buf;pkt.flags = packetList.front().flags;pkt.stream_index = 0;pkt.duration = 48000;pkt.pos += pos;pos = packetList.front().length;packetList.pop_front();cs.Unlock();    //解码码流DecodeVideoFrame(&pkt);}//释放数据包av_free_packet(&pkt);Sleep(10);}else{break;}}Printf("跳出循环,编码结束;\n");
}

解码后播放视频

/*将码流数据解码成视频帧,并进行格式转换,
然后通过SDL播放在MFC对话框上*/
BOOL CVideoDlg::DecodeVideoFrame(AVPacket *pkt)
{int Ret = -1;int got_picture = 0;//将pkt的码流解码到m_picture中Ret = avcodec_decode_video2(m_pCodecCtx,m_picture,&got_picture,pkt);if (Ret < 0){Printf("Error while decoding video frame\n");return 0;}if(1 != got_picture){Printf("could not get decoded video frame\n");return 0;}int width  = m_pCodecCtx->width;int height = m_pCodecCtx->height;//获得像素大小m_PicBytes = avpicture_get_size(PIX_FMT_YUV420P,width,height);m_PicBuf = new uint8_t[m_PicBytes];//为结构体m_pFrame分配存缓冲数据的bufferavpicture_fill((AVPicture*)m_pFrameYUV,m_PicBuf,PIX_FMT_YUV420P,width,height);if (!m_pImgCtx){//将解码后的帧数据转换成YUV420数据m_pImgCtx = sws_getContext(width,height,m_pCodecCtx->pix_fmt,width,height,   PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL);} //转换数据格式sws_scale(m_pImgCtx,(const uint8_t* const*)m_picture->data, m_picture->linesize,0, height, m_pFrameYUV->data, m_pFrameYUV->linesize); //SDL显示------------------------SDL_UpdateTexture(sdlTexture, NULL, m_pFrameYUV->data[0], m_pFrameYUV->linesize[0]);SDL_RenderClear(sdlRenderer);SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);SDL_RenderPresent(sdlRenderer);//SDL End-----------------------delete[] m_PicBuf; //释放内存return Ret;
}

到此,一个视频聊天软件经过:视频采集、编码、码流网络传输、解码、播放流程,终于可以实现了。

VC++实现视频聊天:FFmpeg解码+SDL播放视频相关推荐

  1. Jrtplib发送视频文件 + FFMPEG解码+VFW播放视频 (回调方式)

    在上篇文章<Jrtplib收发H264文件 + FFMPEG解码+VFW播放视频> 里,我们采用的模式是发送端读取本地H264文件, 把完整的Naul(包含起始码) 逐个发送给接收端,接收 ...

  2. 使用ffmpeg和sdl播放视频实现时钟同步

    自定义播放器系列 第一章 视频渲染 第二章 音频(push)播放 第三章 音频(pull)播放 第四章 实现时钟同步(本章) 第五章 实现通用时钟同步 第六章 实现播放器 文章目录 自定义播放器系列 ...

  3. 【FFmpeg】ffplay 播放视频命令 ( 播放 | 暂停 | 停止 | 音量控制 | 进度控制 | 音频流 / 视频流 / 字幕流 / 节目切换 )

    FFmpeg 系列文章目录 [FFmpeg]Windows 搭建 FFmpeg 命令行运行环境 [FFmpeg]FFmpeg 相关术语简介 ( 容器 | 媒体流 | 数据帧 | 数据包 | 编解码器 ...

  4. android全平台基于ffmpeg解码本地MP4视频推流到RTMP服务器

    音视频实践学习 android全平台编译ffmpeg以及x264与fdk-aac实践 ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器 android全平台编译ffm ...

  5. 腾讯视频如何多倍速播放视频

    1.首先打开手机桌面上的"腾讯视频". 怎么下载腾讯视频里的视频_腾讯视频如何多倍速播放视频 2.再进入了腾讯视频的首页后,在首页的页面上选择一个你想要多倍速播放的视频,点击进入这 ...

  6. 腾讯视频真实下载地址_腾讯视频如何多倍速播放视频

    腾讯视频官网版是一款专注视频播放的客户端软件,您可运行腾讯视频,在线享受奇艺网站内全部免费高清正版视频.腾讯视频视频播放器内容丰富,影视更新快,包含腾讯视频所有的视频内容,在线享受腾讯视频站内全部免费 ...

  7. cocos android 播放视频,Cocos2d-x IOS 和Android播放视频

    本篇文章会给大家介绍在对IOS 和Android开发时,是如何实现播放视频这个功能的,下面就分别给大家介绍下. 一. iOS播放本地视频 对于ios平台的视频播放,这里直接使用MediaPlayer. ...

  8. Android 基于GSYVideoPlayer实现短视频软件上下滑自动播放视频

    先放效果图 两个视频的地址: private final String mp4_a = "http://vfx.mtime.cn/Video/2019/03/19/mp4/190319212 ...

  9. ffmpeg解码H.264视频数据,MFC播放视频

    ffmpeg 是一个完整的视频流解决方案,开源且有良好的跨平台性,ffmpeg具有强大的多媒体数据处理能力,能够实现视频的采集,多种视频格式间转换,给视频添加水印等多种功能,已被 VLC.Mplaye ...

最新文章

  1. 下列哪些说法符合《阿里巴巴Java开发手册》
  2. html 后台参数attribute_平台管理后台与商家菜单资源管理:商家权限及其菜单资源管理设计...
  3. Spring mvc集成log4j2
  4. 使用String 的 intern做锁提高并发能力
  5. Python 列表 list() 方法
  6. ES5-1 发展史、ECMA、编程语言、变量、JS值
  7. 通过Spring Boot使用MySQL JDBC驱动程序
  8. bcc挖矿用什么_BCC对BTC挖矿有何影响?
  9. python机械_10分钟掌握Python-机器学习小项目
  10. 【Office Word】论文排版有关技巧
  11. Apache Solr 全文检索概述 与 Win10 下安装 Solr
  12. Java log2x函数的实现
  13. Linux ssh 文件 authorized_keys 和 known_hosts
  14. Windows直接访问WSL2路径并直接进行读写操作,权限不足的问题
  15. PE系统优盘制作教程
  16. 燃烧的远征java(一)-开发环境:JDK1.6+tomcat5.5
  17. 网页爬虫实战:全国电动汽车充电站数据
  18. PDN连接与默认 APN
  19. pkcs1解密 springboot_使用springboot完成密码的加密解密
  20. JavaScript学习笔记|数据类型——Object类型、for in循环

热门文章

  1. 简评起点VIP书架中的书
  2. 两个圆公切线求法_两圆的公切线教案
  3. 【概率论】几何概率、条件概率及全概率公式作业
  4. js实现表格操作-排序
  5. 支付宝大整改,花呗、借呗退出江湖
  6. PS 替换图片上的字
  7. 2012年IT行业十大急需人才
  8. 微软移动 Nokia Lumia SensorCore SDK 介绍及上手体验
  9. 学计算机的电脑用i5还是i7好,家用电脑,选酷睿i7还是选i5,这些常识让你不纠结...
  10. USG 6000v web访问