项目最近需要实现播放视频功能,这个在上家公司就做过。虽然跟之前的场景不一样,有以前的功底还是很快可以解决,事实也确实如此。在使用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. Struct2 自定义拦截器

    1 因为struct2 如文件上传,数据验证等功能都是由系统默认的 defalutStack中的拦截器实现的,所以我们定义拦截器需要引用系统默认的defalutStack 这样才不会影响struct2 ...

  2. running android lint has encountered a problem

    最近写学习android编程的的时候,每次保存.java文件的时候,总会跳出如下错误 解决:

  3. Observer Pattern

    Motivation We can not talk about Object Oriented Programming without considering the state of the ob ...

  4. sql over()---转载

    1.使用over子句与rows_number()以及聚合函数进行使用,可以进行编号以及各种操作.而且利用over子句的分组效率比group by子句的效率更高. 2.在订单表(order)中统计中,生 ...

  5. 【POJ3243】拓展BSGS(附hash版)

    上一篇博文中说道了baby step giant step的方法(简称BSGS),不过对于XY mod Z = K ,若x和z并不互质,则不能直接套用BSGS的方法了. 为什么?因为这时候不存在逆元了 ...

  6. cojs 简单的区间问题 解题报告

    新学了些弦图和区间图的新玩意,于是就想着出一道题目 其实这道题不用弦图和区间图的理论也是可以做的 首先考虑第一问,第一问是一个NOIP普及组水平的贪心 我们把区间按照右端点从小到大排序,之后从头到尾扫 ...

  7. lintcode :Reverse Words in a String 翻转字符串

    题目: 翻转字符串 给定一个字符串,逐个翻转字符串中的每个单词. 样例 给出s = "the sky is blue",返回"blue is sky the" ...

  8. 再谈PCA

        其实之前写过PCA相关的博文,但是由于之前掌握的理论知识有限,所以理解也比较浅.这篇博文,我们以另外一种角度来理解PCA看,这里我假设大家对PCA都有一个初步的了解.首先,我们举一个二维空间中 ...

  9. sparse coding稀疏表达入门

    最近在看sparse and redundant representations这本书,进度比较慢,不过力争看过的都懂,不把时间浪费掉.才看完了不到3页吧,书上基本给出了稀疏表达的概念以及传统的求法. ...

  10. java中什么时候该用static修饰方法?有什么好处或者坏处?

    当一个方法或者变量需要初始化加载,或者是经常被调用的时候可以加上static.用static修饰的方法可以用类名直接调用,不用的一定要先实例化一个对象然后才可以调用比如 person这个类里面有一个方 ...