通过ffmpeg反向播放视频 [英] Reverse video playback through ffmpeg

查看:126
本文介绍了通过ffmpeg反向播放视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ffmpeg多媒体框架实现视频播放器.我能够实现播放,暂停,增加速度,降低速度,向前搜索,向后搜索功能.但是视频的反向播放并不是那么顺畅,它结结巴巴.请帮助我了解视频反向播放.有什么更好的方法呢?

I am implementing a video player using ffmpeg multimedia framework. I am able to achieve play, pause, increase speed, decrease speed, forward seek, backward seek functionalities. But reverse playback of the video is not so smooth, it stutters a lot. Please help me in understanding video reverse playback. What is the better approach for this?

还有其他支持反向视频播放的多媒体框架吗?

Is there any other multimedia framework which support reverse video playback?

非常感谢.

推荐答案

因此,首先,对该问题进行一些框架化.FFmpeg是一个非常低级的库,它试图在原始媒体文件访问的基础上提供一个瘦API.这意味着您基本上可以从字面上获得媒体文件中的内容.对于视频,这是来自解复用器的压缩视频数据包流,然后是来自解码器的已解码图片流.由于B/P帧预测,这是严格的线性和单向过程.还要注意,FFmpeg在大多数实际情况下使用多线程,这也是严格的线性过程.如果您有4个线程解码第8、9、10、11帧,并在此之后尝试到第7帧(因此对第7、8、9和10帧进行解码),则实际上会产生永恒的浪费.

So, first, some framing of this issue. FFmpeg is an extremely low-level library which tries to give a thin API on top of raw media file access. This means that you basically get quite literally what's in the media file. For video, that's the stream of compressed video packets from the demuxer, and then a stream of decoded pictures from the decoder. Because of B/P-frame prediction, this is a strictly linear and unidirectional process. Note also that FFmpeg in most practical cases uses multi-threading, which is again a strictly linear process. If you have 4 thread decoding frame 8, 9, 10, 11, and you seek to frame 7 after that (thus decoding frame 7, 8, 9 and 10), you're essentially generating eternal waste.

因此:使用反向排序的 av_seek_frame()进行反向播放本质上与FFmpeg基本设计不兼容.这并不意味着您根本无法使用FFmpeg 来做到这一点,但是它确实意味着如果您 do 可以使用FFmpeg来做到这一点它,它需要一些努力.话虽如此,您将如何完成反向播放?您缓存了!

So: reverse playback using inverse-ordered av_seek_frame() is inherently incompatible with FFmpeg basic design. That doesn't mean that you can't do it using FFmpeg at all, but it does mean that if you do use FFmpeg to do it, it takes some effort. Having said that, how would you accomplish reverse playback? You cache!

您可以创建N个帧的组(其中N至少与线程数一样大,但仍允许您在内存中保存这么多帧),例如N = 10或N = 100(取决于帧大小).然后,使用对 av_read_frame() avcodec_decode_videoN()的顺序调用来向前解码 N帧,并将它们保存在应用程序的内存中.例如,您现在可能在内存中有第7-17帧.开始显示第17帧,然后下一个显示16、15,依此类推(从内存中),直到达到index = 7.当您点击7时,寻找到下一个位置,以使您可以在内存中保留N帧(在N = 10的情况下,该索引将为index = 0),并在内存中保留第0-6帧,并显示index = 6,5,以此类推,直到0.

You can create groups of N frames (where N is at least as large as the number of threads, but still allows you to hold so many frames in memory), e.g. N=10 or N=100 (depending on frame size). Then, forward-decode N frames using sequential calls to av_read_frame() and avcodec_decode_videoN(), and hold them in memory in your application. For example, you might now have frame 7-17 in memory. Start displaying frame 17, and next display 16, 15, and so on (from memory), until you hit index=7. When you hit 7, seek to the next position allowing you to hold N frames in memory (in the case of N=10, that would be index=0), and hold frame 0-6 in memory, and display index=6, 5 and so on until 0.

我实际上已经实现了这一确切功能,并且使用这种方法可以很好地工作,并且它仍然正确地(几乎)使用多线程.对于高分辨率视频上的N个较大的值,它确实需要占用大量内存,因此建议您使N取决于帧大小,并使N *分辨率可以在应用程序的首选项中设置,或者至少使其依赖于运行该软件的计算机上可用内存的总容量.

I've actually implemented this exact feature and it works quite well using this approach, and it does still use multi-threading (almost) correctly. It does take quite a bit of memory for large N values on high-resolution video, so you're encouraged to make N dependent on frame size and make N * resolution either settable in the preferences of your application, or at least make it depend on the total amount of memory available on the computer the software runs on.

请注意,搜索并不是最容易的事情,因为您无法随机地搜索任何视频中的任何点并期望它能正常工作.对于大多数实现P帧或B帧的编解码器,您只能寻求关键帧或I/IDR帧.这意味着文件格式需要在其索引中设置关键帧标志.如果不是这种情况,则在初始加载文件时必须综合生成索引(例如,调用 av_read_frame()直到遇到EOF为止).

Note that seeking isn't the easiest thing, because you can't randomly seek to any point within any video and expect it to work. For most codecs implementing P-frames or B-frames, you can only seek to keyframes or I/IDR-frames. This means that the file format needs to set the keyframe flag in its index. If that's not the case, you'll have to synthetically generate an index while initially loading the file (e.g. call av_read_frame() until you hit EOF).

关于您的其他问题:我确定还有其他实现特技播放(反向播放等)的媒体框架,例如 GStreamer 可以.但是,这通常仅适用于有限数量的文件格式,

Regarding your other question: I'm sure there's other media frameworks implementing trick play (reverse playback etc.), e.g. GStreamer does. However, this typically works only for a limited number of file formats, not for all supported file formats in the media framework.

这篇关于通过ffmpeg反向播放视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆