ffmpeg播放H264裸流 实现快进快退功能

powerzone 2012-08-28 02:02:32
大家好!我使用ffmpeg的h264标准对摄像头捕获的视频进行编码并保存,得到test.264裸码流文件,并实现对该码流进行解码播放,我现在想要增加该视频播放器的快进快退功能,但没有思路陷于疑惑中,希望有这方面经验的同行分享一下你们的见解,谢谢。
因为是裸码流,不能通过ffmpeg提供的函数获得播放时间和总帧数,如下代码操作无效:
AVFormatContext* pFormatCtx;
int ret = av_open_input_file(&pFormatCtx, fileIn, NULL, 0, NULL);

if (av_open_input_file(&pFormatCtx, fileIn, NULL, 0, NULL) != 0 )
{//读取文件信息的头部并保存到AVFormatContext结构体
//后三个参数:文件格式 缓冲大小 格式参数
fprintf(fLog, "Can't Open video file!\n");
return;
}

if (av_find_stream_info(pFormatCtx) < 0)
{
fprintf(fLog, "There is No stream in File!\n");
return;
}
得到的int dura = pFormatCtx->duration; dura值为0

所以我想不能用这种常规的方式获取播放时间和总帧数。我现在的想法是在编码的时候构建一个结构体包含:编码数据、数据长度和该编码数据块的索引。然后在播放的时候,如果有快进或者拖动,计算进度条的比例然后定位到某一数据块再进行解码播放。但如果这样做的话我又不知道该如何定位每一帧,如何确定关键帧?我原来是用getNextNal函数通过查找0x000001来确定帧开始的,现在不知道该如何去确定了。

另,我用暴风影音播放我的test.264文件能自由拖动,不知道它是怎么实现的?
谢谢!
...全文
3317 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
dai199478 2014-07-03
  • 打赏
  • 举报
回复


诶,刚公司要求定义文件格式,随便写了下,其中的索引好像可以满足你的要求。。。
wangzi400gig 2013-08-21
  • 打赏
  • 举报
回复
可否提供相关代码?谢谢
Shawn4com 2013-08-06
  • 打赏
  • 举报
回复
学习了,视频编解码难度够大了,慢慢熬啊。。
testpwd 2012-12-07
  • 打赏
  • 举报
回复
请问你的思路是怎么样的呢?多谢啊!
powerzone 2012-09-04
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

客气了...只是刚好看到了一个我还能回复一下的帖子
这个版块藏的深,所以回帖的同学就相对会少些...
[/Quote]

问题在2012-08-30即你回复当天就解决了,谢谢dream238的一路指导。但还在忙一些其他事情还来不及总结,带有空的时候将实现思路和主要代码在此向大家分享。
ArcRain 2012-08-30
  • 打赏
  • 举报
回复
客气了...只是刚好看到了一个我还能回复一下的帖子
这个版块藏的深,所以回帖的同学就相对会少些...
ArcRain 2012-08-29
  • 打赏
  • 举报
回复
不用解码图象,NAL都有个NAL TYPE的,检查下NAL负载图象时的类型就可以了,具体的就是SLICE TYPE。
powerzone 2012-08-29
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

以下为个人观点:
你可以装一个Elecard StreamEye的工具,里面有个Stream Analyzer用来分析H264码流的,它会把码流里的各个NAL单元类型以及主要参数解析出来,你可以看下NAL的单元类型序列。
例如这样一个序列: (1) SPS PPS (SEI SEI) IDR (2) (SEI SEI) P (3)(SEI SEI) P....
你可以认为一个完整帧数据是(……
[/Quote]

dream238,一直只有你给我解疑,用什么感激的话都不为过,学习你这种精神。。。

明天到公司再仔细研究一下你在10楼的留言,呵呵,有疑问的话我还是要麻烦你的
powerzone 2012-08-29
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

0x000001只是确定NAL单元,找NAL携带的图象类型是IDR帧或I帧应该就可以了。
[/Quote]

谢谢你的回复。
那么这个图像类型怎么确定呢?是解码后通过FF_I_TYPE == picture->pict_tyep来确定吗?
ArcRain 2012-08-29
  • 打赏
  • 举报
回复
以下为个人观点:
你可以装一个Elecard StreamEye的工具,里面有个Stream Analyzer用来分析H264码流的,它会把码流里的各个NAL单元类型以及主要参数解析出来,你可以看下NAL的单元类型序列。
例如这样一个序列: (1) SPS PPS (SEI SEI) IDR (2) (SEI SEI) P (3)(SEI SEI) P....
你可以认为一个完整帧数据是(1)、(2)、(3)之间的NAL单元总和,如果需要定位的话,那么需要定位的准确位置就是(1)、(2)、(3)这三个地方,同时(SEI)的数据针对不同类型的视频文件,可能有也可能无,但对于解码来说,SPS,PPS是必不可少的。所以如果只定位到IDR那个地方,也是不准确的。
NAL单元里有个类型为9的访问控制头,同样的有些文件有,有些文件没。有的话,一般就是(1),(2),(3)所处的位置,所以可以很方便的把两个类型为9的NAL单元之间的数据确立为一个可靠的帧数据。如果没有的话,就只能通过其他手段来判断了,会复杂些,因为需要根据当前的NAL类型以及前面的NAL类型来确认。
当然,由于文件的编码方式多样,就算是H264,在帧序列和NAL组成上也会各有差异的,具体还需要针对实际文件来分析。
ArcRain 2012-08-29
  • 打赏
  • 举报
回复
0x000001只是确定NAL单元,找NAL携带的图象类型是IDR帧或I帧应该就可以了。
powerzone 2012-08-29
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

如果是裸码流,没有文件容器相关的信息来描述,估计只能这样遍历来数了,遍历的时候只解析关心的数据,不关心的就跳过去好了,速度应该还行的。
FFMPEG其实我没用过,只是了解些H264的东西。
H264码流的话还是要看SPEC文档,这样才能对照代码知道解析时的具体参数意义。
关于H264文档可以GOOGLE找下。
[/Quote]

你曾在http://topic.csdn.net/u/20111123/18/95e6ce88-3233-4c1c-8e67-347c4417fb50.html
该帖子中对一个NAL是否是一帧的判断进行了描述,但我不是很明白这个内容,能稍微解释一下吗?

我的意思是我怎么可以通过NAL来确实是否是一帧?

谢谢!
powerzone 2012-08-29
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

如果是裸码流,没有文件容器相关的信息来描述,估计只能这样遍历来数了,遍历的时候只解析关心的数据,不关心的就跳过去好了,速度应该还行的。
FFMPEG其实我没用过,只是了解些H264的东西。
H264码流的话还是要看SPEC文档,这样才能对照代码知道解析时的具体参数意义。
关于H264文档可以GOOGLE找下。
[/Quote]

dream238,你真是太热心了,充满社区精神,值得学习,谢谢。
嗯,是裸码流,领导要求不能用容器。我是的担心如果文件太大的话,先遍历的话会很费时间。

ArcRain 2012-08-29
  • 打赏
  • 举报
回复
如果是裸码流,没有文件容器相关的信息来描述,估计只能这样遍历来数了,遍历的时候只解析关心的数据,不关心的就跳过去好了,速度应该还行的。
FFMPEG其实我没用过,只是了解些H264的东西。
H264码流的话还是要看SPEC文档,这样才能对照代码知道解析时的具体参数意义。
关于H264文档可以GOOGLE找下。
powerzone 2012-08-29
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

1)总帧数数帧就可以了,时长的话用帧数除以播放帧率应该可以算出来。
2)你的理解是对的,以I或IDR的位置开始播放,因为P帧、B帧无法单独解出来,必须有参考帧。
[/Quote]

再次谢谢你的回复。

数帧?你的意思是先遍历一遍该码流文件,得出总帧数,然后在播放的时候使用?如果这样的话,岂不是要读取该文件2次,因为播放的时候还得读取一次。
因为我这方面基础不好,也没研读过ffmpeg协议,万望你解释细点,呵呵。
ArcRain 2012-08-29
  • 打赏
  • 举报
回复
1)总帧数数帧就可以了,时长的话用帧数除以播放帧率应该可以算出来。
2)你的理解是对的,以I或IDR的位置开始播放,因为P帧、B帧无法单独解出来,必须有参考帧。
powerzone 2012-08-29
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

不用解码图象,NAL都有个NAL TYPE的,检查下NAL负载图象时的类型就可以了,具体的就是SLICE TYPE。
[/Quote]

谢谢你的回复。我由找了一个下午的资料,还是没有头绪该如何去实现。

按照你的意思,nal_unit_type = 5 可以判断其是I帧,但是我该如何去获得该码流的总帧数和播放时长呢,或者通过什么方式计算呢?
我的理解是,快进或拖动到某一个地方,则可以算出到哪一帧,对该帧的NAL进行分析,如果是I帧就开始播放,否则继续往后查找?

2,543

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧