Подтвердить что ты не робот

С++: какая самая простая библиотека для открытия видеофайла

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

Я попытался использовать 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 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 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;

    [...]
}

[...]

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

Спасибо

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

Ответ 3

Использование модели "Обратный звонок" SampleGrabber может дать вам лучшие результаты. См. Пример в примерах\С++\DirectShow\Редактирование\GrabBitmaps.

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

Ответ 4

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

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

Ответ 5

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

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

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

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

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

Ответ 6

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

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

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

Ответ 7

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

Вместо этого рекомендую 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 tool, эта часть собирает информацию о видео. Я помещал FFmpeg в определенное место, и в начале запуска программного обеспечения он уверен, что он есть. Для этой версии я переместил ее на рабочий стол, я уверен, что правильно написал путь для вас (я действительно ненавижу систему специальных папок MS, поэтому я игнорирую ее как можно больше).

Во всяком случае, это пример использования windowless 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"));
        }
    }