C++:打开视频文件最简单的库是什么
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ : What's the easiest library to open video file
提问by Steve Gury
I would like to open a small video file and map every frames in memory (to apply some custom filter). I don't want to handle the video codec, I would rather let the library handle that for me.
我想打开一个小视频文件并映射内存中的每一帧(应用一些自定义过滤器)。我不想处理视频编解码器,我宁愿让库为我处理。
I've tried to use Direct Show with the SampleGrabber filter (using this sample http://msdn.microsoft.com/en-us/library/ms787867(VS.85).aspx), but I only managed to grab some frames (not every frames!). I'm quite new in video software programming, maybe I'm not using the best library, or I'm doing it wrong.
我尝试将 Direct Show 与 SampleGrabber 过滤器一起使用(使用此示例http://msdn.microsoft.com/en-us/library/ms787867(VS.85).aspx),但我只设法抓取了一些帧(不是每一帧!)。我是视频软件编程的新手,也许我没有使用最好的库,或者我做错了。
I've pasted a part of my code (mainly a modified copy/paste from the msdn example), unfortunately it doesn't grabb the 25 first frames as expected...
我已经粘贴了我的一部分代码(主要是来自 msdn 示例的修改后的复制/粘贴),不幸的是它没有按预期抓取 25 个第一帧......
[...]
hr = pGrabber->SetOneShot(TRUE);
hr = pGrabber->SetBufferSamples(TRUE);
pControl->Run(); // Run the graph.
pEvent->WaitForCompletion(INFINITE, &evCode); // Wait till it's done.
// Find the required buffer size.
long cbBuffer = 0;
hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
for( int i = 0 ; i < 25 ; ++i )
{
pControl->Run(); // Run the graph.
pEvent->WaitForCompletion(INFINITE, &evCode); // Wait till it's done.
char *pBuffer = new char[cbBuffer];
hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);
AM_MEDIA_TYPE mt;
hr = pGrabber->GetConnectedMediaType(&mt);
VIDEOINFOHEADER *pVih;
pVih = (VIDEOINFOHEADER*)mt.pbFormat;
[...]
}
[...]
Is there somebody, with video software experience, who can advise me about code or other simpler library?
有没有人有视频软件经验,可以就代码或其他更简单的库向我提出建议?
Thanks
谢谢
Edit: Msdn links seems not to work (see the bug)
编辑:Msdn 链接似乎不起作用(请参阅错误)
回答by martjno
Currently these are the most popular video frameworks available on Win32 platforms:
目前,这些是 Win32 平台上可用的最流行的视频框架:
Video for Windows: old windows framework coming from the age of Win95 but still widely used because it is very simple to use. Unfortunately it supports only AVI files for which the proper VFW codec has been installed.
DirectShow: standard WinXP framework, it can basically load all formats you can play with Windows Media Player. Rather difficult to use.
Ffmpeg: more precisely libavcodec and libavformat that comes with Ffmpeg open- source multimedia utility. It is extremely powerful and can read a lot of formats (almost everything you can play with VLC) even if you don't have the codec installed on the system. It's quite complicated to use but you can always get inspired by the code of ffplay that comes shipped with it or by other implementations in open-source software. Anyway I think it's still much easier to use than DS (and much faster). It needs to be comipled by MinGW on Windows, but all the steps are explained very well here(in this moment the link is down, hope not dead).
QuickTime: the Apple framework is not the best solution for Windows platform, since it needs QuickTime app to be installed and also the proper QuickTime codec for every format; it does not support many formats, but its quite common in professional field (so some codec are actually only for QuickTime). Shouldn't be too difficult to implement.
Gstreamer: latest open source framework. I don't know much about it, I guess it wraps over some of the other systems (but I'm not sure).
Video for Windows:来自 Win95 时代的旧 Windows 框架,但仍被广泛使用,因为它使用起来非常简单。不幸的是,它只支持安装了正确 VFW 编解码器的 AVI 文件。
DirectShow:标准的WinXP 框架,它基本上可以加载Windows Media Player 可以播放的所有格式。比较难用。
Ffmpeg:更准确地说,是 Ffmpeg 开源多媒体实用程序附带的 libavcodec 和 libavformat。它非常强大,即使您没有在系统上安装编解码器,也可以读取多种格式(几乎所有您可以使用VLC播放的格式)。它使用起来非常复杂,但您总是可以从随附的 ffplay 代码或开源软件中的其他实现中获得灵感。无论如何,我认为它仍然比 DS 更容易使用(而且速度更快)。需要在windows上用MinGW编译,不过所有的步骤在这里都解释的很好(此时链接挂了,希望没死)。
QuickTime:Apple 框架不是 Windows 平台的最佳解决方案,因为它需要安装 QuickTime 应用程序以及适合每种格式的 QuickTime 编解码器;它不支持很多格式,但它在专业领域很常见(所以一些编解码器实际上只适用于 QuickTime)。实施起来应该不会太难。
Gstreamer:最新的开源框架。我对它了解不多,我猜它包含了其他一些系统(但我不确定)。
All of this frameworks have been implemented as backend in OpenCv Highgui, except for DirectShow. The default framework for Win32 OpenCV is using VFW (and thus able only to open some AVI files), if you want to use the others you must download the CVS instead of the official release and still do some hacking on the code and it's anyway not too complete, for example FFMPEG backend doesn't allow to seek in the stream. If you want to use QuickTime with OpenCV thiscan help you.
除 DirectShow 外,所有这些框架都已在 OpenCv Highgui 中作为后端实现。Win32 OpenCV 的默认框架是使用 VFW(因此只能打开一些 AVI 文件),如果你想使用其他文件,你必须下载 CVS 而不是官方版本,并且仍然对代码进行一些黑客攻击,无论如何都不是太完整了,例如 FFMPEG 后端不允许在流中查找。如果您想在 OpenCV 中使用 QuickTime,这可以帮助您。
回答by Chris de Vries
回答by Bob
I know it is very tempting in C++ to get a proper breakdown of the video files and just do it yourself. But although the information is out there, it is such a long winded process building classes to hand each file format, and make it easily alterable to take future structure changes into account, that frankly it just is not worth the effort.
我知道在 C++ 中获得视频文件的正确分解并自己做是非常诱人的。但是,尽管信息在那里,但是处理每种文件格式的构建类是一个冗长的过程,并且可以很容易地更改以考虑未来的结构变化,坦率地说,这不值得付出努力。
Instead I recommend ffmpeg. It got a mention above, but says it is difficult, it isn't difficult. There are a lot more options than most people would need which makes it look more difficult than it is. For the majority of operations you can just let ffmpeg work it out for itself.
相反,我推荐 ffmpeg。上面有提到,但说难,不难。有比大多数人需要的更多的选择,这使得它看起来比它更困难。对于大多数操作,您可以让 ffmpeg 自行解决。
For example a file conversion ffmpeg -i inputFile.mp4 outputFile.avi
例如一个文件转换 ffmpeg -i inputFile.mp4 outputFile.avi
Decide right from the start that you will have ffmpeg operations run in a thread, or more precisely a thread library. But have your own thread class wrap it so that you can have your own EventAgs and methods of checking the thread is finished. Something like :-
从一开始就决定您将在线程中运行 ffmpeg 操作,或者更准确地说是在线程库中运行。但是让你自己的线程类包装它,这样你就可以拥有自己的 EventAgs 和检查线程是否完成的方法。就像是 :-
ThreadLibManager()
{
List<MyThreads> listOfActiveThreads;
public AddThread(MyThreads);
}
Your thread class is something like:-
class MyThread
{
public Thread threadForThisInstance { get; set; }
public MyFFMpegTools mpegTools { get; set; }
}
MyFFMpegTools performs many different video operations, so you want your own event
args to tell your parent code precisely what type of operation has just raised and
event.
enum MyFmpegArgs
{
public int thisThreadID { get; set; } //Set as a new MyThread is added to the List<>
public MyFfmpegType operationType {get; set;}
//output paths etc that the parent handler will need to find output files
}
enum MyFfmpegType
{
FF_CONVERTFILE = 0, FF_CREATETHUMBNAIL, FF_EXTRACTFRAMES ...
}
Here is a small snippet of my ffmpeg tool class, this part collecting information about a video. I put FFmpeg in a particular location, and at the start of the software running it makes sure that it is there. For this version I have moved it to the Desktop, I am fairly sure I have written the path correctly for you (I really hate MS's special folders system, so I ignore it as much as I can).
这是我的 ffmpeg 工具类的一小段,这部分收集有关视频的信息。我把 FFmpeg 放在一个特定的位置,在软件运行的开始,它确保它在那里。对于这个版本,我已将其移至桌面,我很确定我已为您正确编写了路径(我真的很讨厌 MS 的特殊文件夹系统,所以我尽可能地忽略它)。
Anyway, it is an example of using windowless ffmpeg.
无论如何,它是使用无窗口ffmpeg的示例。
public string GetVideoInfo(FileInfo fi)
{
outputBuilder.Clear();
string strCommand = string.Concat(" -i \"", fi.FullName, "\"");
string ffPath =
System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\ffmpeg.exe";
string oStr = "";
try
{
Process build = new Process();
//build.StartInfo.WorkingDirectory = @"dir";
build.StartInfo.Arguments = strCommand;
build.StartInfo.FileName = ffPath;
build.StartInfo.UseShellExecute = false;
build.StartInfo.RedirectStandardOutput = true;
build.StartInfo.RedirectStandardError = true;
build.StartInfo.CreateNoWindow = true;
build.ErrorDataReceived += build_ErrorDataReceived;
build.OutputDataReceived += build_ErrorDataReceived;
build.EnableRaisingEvents = true;
build.Start();
build.BeginOutputReadLine();
build.BeginErrorReadLine();
build.WaitForExit();
string findThis = "start";
int offset = 0;
foreach (string str in outputBuilder)
{
if (str.Contains("Duration"))
{
offset = str.IndexOf(findThis);
oStr = str.Substring(0, offset);
}
}
}
catch
{
oStr = "Error collecting file information";
}
return oStr;
}
private void build_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
string strMessage = e.Data;
if (outputBuilder != null && strMessage != null)
{
outputBuilder.Add(string.Concat(strMessage, "\n"));
}
}
回答by Adam Mitz
Using the "Callback" model of SampleGrabber may give you better results. See the example in Samples\C++\DirectShow\Editing\GrabBitmaps.
使用 SampleGrabber 的“回调”模型可能会给你更好的结果。请参阅 Samples\C++\DirectShow\Editing\GrabBitmaps 中的示例。
There's also a lot of info in Samples\C++\DirectShow\Filters\Grabber2\grabber_text.txt and readme.txt.
Samples\C++\DirectShow\Filters\Grabber2\grabber_text.txt 和 readme.txt 中也有很多信息。
回答by Jimmy J
If it's for AVI files I'd read the data from the AVI file myself and extract the frames. Now use the video compression manager to decompress it.
如果是 AVI 文件,我会自己从 AVI 文件中读取数据并提取帧。现在使用视频压缩管理器解压缩它。
The AVI file format is very simple, see: http://msdn.microsoft.com/en-us/library/dd318187(VS.85).aspx(and use google).
AVI 文件格式非常简单,请参阅:http: //msdn.microsoft.com/en-us/library/dd318187(VS.85) .aspx(并使用 google)。
Once you have the file open you just extract each frame and pass it to ICDecompress() to decompress it.
打开文件后,您只需提取每一帧并将其传递给 ICDecompress() 以对其进行解压缩。
It seems like a lot of work but it's the most reliable way.
这看起来像很多工作,但这是最可靠的方式。
If that's too much work, or if you want more than AVI files then use ffmpeg.
如果工作量太大,或者您想要的不仅仅是 AVI 文件,请使用 ffmpeg。
回答by DJKylix
OpenCV is the best solution if video in your case only needs to lead to a sequence of pictures. If you're willing to do real video processing, so ViDeo equals "Visual Audio", you need to keep up track with the ones offered by "martjno". New windows solutions also for Win7 include 3 new possibilities additionally:
如果您的视频只需要生成一系列图片,OpenCV 是最佳解决方案。如果你愿意做真正的视频处理,那么 ViDeo 就等于“视觉音频”,你需要跟上“martjno”提供的那些。Win7 的新 Windows 解决方案还包括 3 个新的可能性:
- Windows Media Foundation: Successor of DirectShow; cleaned-up interface
- Windows Media Encoder 9: It does not only include the programm, it also ships libraries for coding
- Windows Expression 4: Successor of 2.
- Windows Media Foundation:DirectShow 的继任者;清理界面
- Windows Media Encoder 9:它不仅包括程序,还提供编码库
- Windows 表达式 4:2 的后继者。
Last 2 are commercial-only solutions, but the first one is free. To code WMF, you need to install the Windows SDK.
最后两个是仅限商业的解决方案,但第一个是免费的。要编写 WMF,您需要安装 Windows SDK。
回答by Lehane
Try using the OpenCVlibrary. It definitely has the capabilities you require.
尝试使用OpenCV库。它绝对具有您需要的功能。
This guidehas a section about accessing frames from a video file.
本指南有一个关于从视频文件访问帧的部分。