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

    Eclipse + ADT +SDK,下载ADT Bundle全包含 adt-bundle-windows-x86_64-20140702 http://www.cnblogs.com/tc310/p ...

  2. dll 入口函数

    http://support.microsoft.com/kb/815065/zh-cn // SampleDLL.cpp // #include "stdafx.h" #defi ...

  3. 多线程Java Socket编程示例(转)

    这篇做为学习孙卫琴<<Java网络编程精解>>的学习笔记吧.其中采用Java 5的ExecutorService来进行线程池的方式实现多线程,模拟客户端多用户向同一服务器端发送 ...

  4. spring mvc 注解 annot失效

    如果带上事务,那么用annotation方式的事务注解和bean配置,事务会失效,要将service bean配置到xml文件中才行 这个问题是由于问答上有解决方案 引用 这个问题很经典了 在主容器中 ...

  5. android 解析XML方式(三)

    上一节中,我们使用SAX方式解析xml文档, SAX方式是基于事件驱动的.当然android的事件机制是基于回调函数的.在这一节中,我们用另外一种方式解析xml文档,这种方式也是基于事件驱动的,与SA ...

  6. hdoj 1596 find the safest road

    题目传送:http://acm.hdu.edu.cn/showproblem.php?pid=1596 分析:Dijkstra变体,最短路径判断计算方式:Safe(P) = s(e1)*s(e2)…* ...

  7. 2014多校第一场J题 || HDU 4870 Rating(DP || 高斯消元)

    题目链接 题意 :小女孩注册了两个比赛的帐号,初始分值都为0,每做一次比赛如果排名在前两百名,rating涨50,否则降100,告诉你她每次比赛在前两百名的概率p,如果她每次做题都用两个账号中分数低的 ...

  8. MySQL 卸载 --Mac

    pkill mysql sudo rm /usr/local/mysql sudo rm -rf /usr/local/mysql* sudo rm -rf /Library/StartupItems ...

  9. ASP.NET并发处理

    http://blog.csdn.net/hliq5399/article/details/6280288

  10. [Unity菜鸟] Character控制移动

    1. 给角色加角色控制器组件,然后用以下代码可以控制角色移动和跳跃 float speed = 6.0f; float jumpSpeed = 8.0f; float gravity = 20.0f; ...