项目最近需要实现播放视频功能,这个在上家公司就做过。虽然跟之前的场景不一样,有以前的功底还是很快可以解决,事实也确实如此。在使用DShow处理完视频分割与合并后,继续使用DShow显示视频,很快即完成。然而在播放dvr录制的视频文件时,发现播放帧率不对,分析发现是dvr存储的视频文件不是按标准格式进行存储(使用ffplay效果还好点,media player根本没法播放),于是重写代码。

先简要说明一下项目:client是delphi开发的GUI程序,视频所有操作功能都由mfc dll实现,这个dll也就是由我实现。delphi只传入要显示视频的窗口句柄、操作类型、文件名,这个跟我在以前设计但未能完工的显示流媒体库有不少借鉴作用,因此在此记录一下。

使用ffmpeg一直到读取文件每一帧、解码,剩下就是显示的工作:解码每一帧的rgb数据在CDC上显示,显示过程中一开始通过CreateDIBSection创建一个HBITMAP对象,memorydc中选入,然后在显示cdc中StretchBlt,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bmpInfoHdr.biPlanes = 1;
bmpInfoHdr.biBitCount = 24;
bmpInfoHdr.biWidth = pAvCdcCtx->width;
bmpInfoHdr.biHeight = pAvCdcCtx->height;
bmpInfoHdr.biSizeImage = nBytes;
bmpInfoHdr.biSize = sizeof(bmpInfoHdr);
 
//创建DIB HBITMAP
hBmpShow = CreateDIBSection(NULL, (BITMAPINFO*)&bmpInfoHdr, DIB_RGB_COLORS, (void**)&pRgbData, NULL, 0);
if (!hBmpShow) {
    itrace("CreateDIBSection failed %d", GetLastError());
    continue;
}
memcpy(pRgbData, pBmpRgbData, nBytes);
 
//显示图片
hBmpBackup = (HBITMAP)m_memDc.SelectObject(hBmpShow);
m_pShowDc->StretchBlt(0, 0, m_width, m_height, &m_memDc, 0, 0,
        pAvCdcCtx->width, pAvCdcCtx->height, SRCCOPY);

结果发现现实视频效果极差,转而研究ffplay代码,发现ffplay分读线程与解码线程。怀疑是播放前未能读取足够的视频帧进行缓存,导致视频在解码播放过程中出现因读取视频占用时间导致效果极差的原因。于是在代码中添加了读/解码线程,修改后发现播放效果没有任何改善。于是排除帧缓冲导致播放问题,这时候看到了yuv viewer代码,发现其显示是通过StretchDIBits实现,且不需要通过CreateDIBSection创建HBITMAP对象。尝试修改代码,播放效果非常好,代码如下

1
2
3
4
m_pShowDc->SetStretchBltMode(STRETCH_DELETESCANS);
StretchDIBits(m_pShowDc->m_hDC, 0, 0, m_width, m_height,
        0, 0, pAvCdcCtx->width, pAvCdcCtx->height,
        pBmpRgbData, (BITMAPINFO*)&bmpInfoHdr, DIB_RGB_COLORS, SRCCOPY);

====视频定位

可以通过前进或者后退多少秒以及百分比对视频进行定位,其实都是获取其绝对时间通过av_rescale_q转成ffmpeg所需要的时间格式,进行视频定位。

我们知道可以通过av_q2d(m_pAvFmtCtx->streams[i]->time_base)* pAvFrame->best_effort_timestamp来获取当前播放时间

1
2
3
AVRational bp = {1, AV_TIME_BASE};
target_pos = av_rescale_q(target_pos, bp, m_pAvFmtCtx->streams[idx]->time_base);
av_seek_frame(m_pAvFmtCtx, idx, target_pos, AVSEEK_FLAG_ANY);

ffmpeg显示视频的更多相关文章

  1. ffmpeg为视频添加时间戳 - 手动编译ffmpeg

    FFMPEG给视频加时间戳水印 项目中需要给视频添加时间戳,理所当然最好用的办法是ffmpeg.在找到正确的做法前,还被网上的答案timecode给水了一下(水的不轻,在这里转了2天),大概是这样写的 ...

  2. 利用FFmpeg生成视频缩略图 2.1.6

    利用FFmpeg生成视频缩略图 1.下载FFmpeg文件包,解压包里的\bin\下的文件解压到 D:\ffmpeg\ 目录下. 下载地址 http://ffmpeg.zeranoe.com/build ...

  3. 使用ffmpeg 对视频截图,和视频转换格式

    //执行CMD命令方法 public static void CmdProcess(string command)//调用CMD        {            //实例化一个进程类      ...

  4. NET 2.0(C#)调用ffmpeg处理视频的方法

    另外:ffmpeg的net封装库 http://www.intuitive.sk/fflib/ NET 2.0 调用FFMPEG,并异步读取输出信息的代码...public void ConvertV ...

  5. 使用FFMPeg对视频进行处理

    FFMPeg处理视频的核心操作方式是命令,无论是在Windows上还是Linux上.那么下边就简单介绍下,常见的处理命令. 示例1:截取一张352×240尺寸大小的,格式为jpg的图片: ffmpeg ...

  6. Java Web 中使用ffmpeg实现视频转码、视频截图

    Java Web 中使用ffmpeg实现视频转码.视频截图 转载自:[ http://www.cnblogs.com/dennisit/archive/2013/02/16/2913287.html  ...

  7. php使用ffmpeg向视频中添加文字字幕

    这篇文章主要介绍了PHP使用ffmpeg给视频增加字幕显示的方法,实例分析了php操作ffmpeg给视频增加字母的技巧,具有一定参考借鉴价值,需要的朋友可以参考下. 本文实例讲述了PHP使用ffmpe ...

  8. (原)使用ass字幕文件通过ffmpeg给视频添加字幕的一些研究

    使用ass字幕文件通过ffmpeg给视频添加字幕的一些研究 Author:lihaiping1603@aliyun.com Create:2019-09-04 最近对ffmpeg给视频文件添加字幕效果 ...

  9. OpenCV-Python 读取显示视频 | 六

    目标 学习读取视频,显示视频和保存视频. 学习从相机捕捉并显示它. 你将学习以下功能:cv.VideoCapture(),cv.VideoWriter() 从相机中读取视频 通常情况下,我们必须用摄像 ...

随机推荐

  1. C#枚举注释实例

    public enum 枚举名称    {        /// <summary>        /// 注释描述1        /// </summary>        ...

  2. PHP读取xml之cdata讲解

    实例: xss.xml <?xml version="1.0" encoding="UTF-8"?><filters>    <f ...

  3. .bash_profile备份

    # ~/.bash_profile # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi # User sp ...

  4. Unity3D 游戏开发应用篇——每日登陆(持久化类实现)

    上一篇中我们实现用本地文件实现了持久化类的保存,当然小型数据用PlayerPrefs存储,或者采用XML服务器持久化也行.因为我涉及的角色类和玩家类数据比较多,加上项目要求尽量少与服务器交互,所以采用 ...

  5. Cloud Insight 仪表盘上线 | 全面监控 Redis

    OneAPM 作为应用性能领域的新兴领军企业,近期发布了重量级新产品-- Cloud Insight 数据管理平台,用它能够监控所有基础组件,并通过 tag 标签对数据进行管理. 近日,Cloud I ...

  6. Redis学习笔记(十)——过期时间、访问限制与缓存

    http://irfen.me/redis-learn-10-time-expire-limit-cache/ 过期时间 之前应该提到过 redis 的特性之一是可以设置键的超时时间.命令是expir ...

  7. Relevance Between Variable Declaration and Definition in C++

    A declaration makes a name known to a programm. A definition creates the assocatied entity. A variab ...

  8. 【转载】Eclipse自动编译问题

    今天调试的时候发现问题:调试的时候竟然在我注释的里面走,当时那个郁闷啊,每次都要clean下才可以,晚上感觉不对劲,上网查了查,原来是bulid automatically这个我把勾去掉了,下面是原文 ...

  9. [主席树]SPOJ DQUERY

    题目链接 题意:n个数 m个查询 查询的是[l, r]区间内不相同的数的个数 没有修改,因此静态的主席树就好了 将重复的元素建树即可 query的时候加起来,用区间长度(r-l+1)去减就是答案 (q ...

  10. 量化生产力Quantifying Productivity

    I'm always on a lookout for interesting datasets to collect, analyze and interpret. And what better ...