C ++: какая библиотека проще для открытия видео файла - PullRequest
23 голосов
/ 01 сентября 2008

Я хотел бы открыть небольшой видеофайл и отобразить каждый кадр в памяти (чтобы применить какой-то пользовательский фильтр). Я не хочу обрабатывать видеокодек, я бы предпочел, чтобы библиотека справилась с этим для меня.

Я пытался использовать Direct Show с фильтром SampleGrabber (используя этот пример http://msdn.microsoft.com/en-us/library/ms787867(VS.85).aspx),, но мне удалось захватить только некоторые кадры (не все кадры!). Я довольно нов в программировании видео, возможно, я не использую лучшую библиотеку, или я делаю это неправильно.

Я вставил часть своего кода (в основном, измененную копию / вставку из примера 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;

    [...]
}

[...]

Есть ли кто-нибудь, имеющий опыт работы с видео, который может посоветовать мне код или другую более простую библиотеку?

Спасибо

Edit: Msdn ссылки, похоже, не работают ( см. Ошибку )

Ответы [ 7 ]

28 голосов
/ 01 сентября 2008

В настоящее время это самые популярные видео-фреймворки, доступные на платформах Win32:

  1. Видео для Windows: старая платформа Windows, пришедшая из эпохи Win95, но все еще широко используемая, потому что она очень проста в использовании. К сожалению, он поддерживает только файлы AVI, для которых установлен соответствующий кодек VFW.

  2. DirectShow: стандартная среда WinXP, она может в основном загружать все форматы, которые можно воспроизводить с помощью проигрывателя Windows Media. Сложно использовать.

  3. Ffmpeg : точнее, libavcodec и libavformat, которые поставляются с мультимедийной утилитой с открытым исходным кодом Ffmpeg. Он чрезвычайно мощный и может читать множество форматов (почти все, что вы можете играть с VLC ), даже если в системе не установлен кодек. Его довольно сложно использовать, но вы всегда можете получить вдохновение от кода ffplay, который поставляется с ним, или от других реализаций в программном обеспечении с открытым исходным кодом. Во всяком случае, я думаю, что это все еще намного проще в использовании, чем DS (и намного быстрее). MinGW на Windows должен его откомпилировать, но все шаги объяснены очень хорошо здесь (в данный момент ссылка не работает, надеюсь, что не мертва).

  4. QuickTime : платформа Apple - не лучшее решение для платформы Windows, поскольку для нее требуется приложение QuickTime, а также надлежащий кодек QuickTime для каждого формата; он не поддерживает много форматов, но довольно распространен в профессиональной области (поэтому некоторые кодеки на самом деле предназначены только для QuickTime). Не должно быть слишком сложно для реализации.

  5. Gstreamer : последний фреймворк с открытым исходным кодом. Я не знаю много об этом, я думаю, что это охватывает некоторые другие системы (но я не уверен).

Все эти фреймворки были реализованы как бэкэнд в OpenCv Highgui, кроме DirectShow. Платформа по умолчанию для Win32 OpenCV использует VFW (и, следовательно, может открывать только некоторые файлы AVI). Если вы хотите использовать другие файлы, вы должны загрузить CVS вместо официального релиза и все же взломать код, но в любом случае это не так. слишком полный, например, бэкэнд FFMPEG не позволяет искать в потоке. Если вы хотите использовать QuickTime с OpenCV , вам может помочь .

2 голосов
/ 21 января 2014

Я знаю, что в C ++ очень заманчиво получить правильную разбивку видеофайлов и просто сделать это самостоятельно. Но, несмотря на то, что информация там есть, это такие затянутые классы построения процессов, которые позволяют обрабатывать каждый формат файла и легко изменять его, чтобы учитывать будущие изменения структуры, что, честно говоря, это просто не стоит усилий.

Вместо этого я рекомендую ffmpeg. Это упоминалось выше, но говорит, что это сложно, это не сложно. Есть гораздо больше вариантов, чем нужно большинству людей, что делает его более сложным, чем он есть. Для большинства операций вы можете просто позволить ffmpeg все сделать самостоятельно.

Например преобразование файла ffmpeg -i inputFile.mp4 outputFile.avi

С самого начала определите, какие операции 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 ...
}

Вот небольшой фрагмент моего класса инструментов ffmpeg, в этой части собрана информация о видео. Я помещаю FFmpeg в определенное место, и в начале работы программного обеспечения оно удостоверяется, что оно там есть. Для этой версии я переместил его на рабочий стол, я уверен, что правильно написал для вас путь (я действительно ненавижу систему специальных папок MS, поэтому я игнорирую ее настолько, насколько могу).

В любом случае, это пример использования 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"));
        }
    } 
2 голосов
/ 01 сентября 2008

Использование модели «Обратный звонок» SampleGrabber может дать вам лучшие результаты. Смотрите пример в Samples \ C ++ \ DirectShow \ Editing \ GrabBitmaps.

Существует также много информации в Samples \ C ++ \ DirectShow \ Filters \ Grabber2 \ grabber_text.txt и readme.txt.

2 голосов
/ 01 сентября 2008

Я использовал OpenCV для загрузки видеофайлов и их обработки. Это также удобно для многих типов обработки видео, включая те, которые полезны для компьютерного зрения.

1 голос
/ 21 сентября 2010

OpenCV - лучшее решение, если видео в вашем случае должно приводить только к последовательности изображений. Если вы готовы выполнять реальную обработку видео, поэтому ViDeo равен «Visual Audio», вам нужно идти в ногу с теми, что предлагает «martjno». Новые решения Windows также для Win7 включают в себя 3 новые возможности дополнительно:

  1. Windows Media Foundation: наследник DirectShow; очищенный интерфейс
  2. Windows Media Encoder 9: он не только включает программу, но и поставляет библиотеки для кодирования
  3. Windows Expression 4: наследник 2.

Последние 2 являются коммерческими решениями, но первое является бесплатным. Чтобы кодировать WMF, вам нужно установить Windows SDK.

1 голос
/ 16 мая 2009

Если бы это было для файлов AVI, я бы сам прочитал данные из файла AVI и вынул кадры. Теперь используйте менеджер сжатия видео, чтобы распаковать его.

Формат файла AVI очень прост, см .: http://msdn.microsoft.com/en-us/library/dd318187(VS.85).aspx (и используйте Google).

После открытия файла вы просто извлекаете каждый кадр и передаете его в ICDecompress (), чтобы распаковать его.

Вроде бы много работы, но это самый надежный способ.

Если это слишком много работы или если вы хотите больше, чем AVI-файлы, используйте ffmpeg.

1 голос
/ 01 сентября 2008

Попробуйте использовать библиотеку OpenCV . Он определенно обладает теми возможностями, которые вам необходимы.

В этом руководстве есть раздел о доступе к кадрам из видеофайла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...