Проблемы при разработке видеоплеера на основе FFMPEG и SDL

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Nebesny
Сообщения: 4
Зарегистрирован: 29 янв 2015, 19:33

Всем доброго времени суток!
Разрабатываю видеоплеер с помощью библиотек FFMPEG и SDL на 13 студии.
Статья о том как это все делать здесь: http://habrahabr.ru/post/137793/
Все вроде бы хорошо, но...
1 проблема: отсутствие некоторых функций в SDL.h, таких как SDL_SetVideoMode, SDL_CreateYUVOverlay, SDL_DisplayYUVOverlay... что-то об этом в этой статье не упоминается.
Но вроде как с горем пополам решил эту проблему: скачал SDL.dll и оттуда путем явного связывания и создания указателей на эти функции вытащил их адреса с помощью GetProcAddress. Через ж*пу, конечно, ну а есть другие варианты?
И тут возникла 2 проблема: после компиляции запускается консоль, где красиво расписываются все параметры видео, затем появляется окно в котором по идее я должен увидеть видео и похлопать в ладоши, но кроме черного экрана ничего я собственно не вижу. Причем 3 минутное видео отображается 10 секундным черным экраном и программа завершает свою работу.
Может кто-то сталкивался с такой проблемой?
Или может есть рабочие исходники видеоплеера на студии?
Буду признателен любым ответам и советам!
Всем спасибо!
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

Ниже приведён пример кода простейшего консольного медиа-проигрывателя, который использует Windows-платформу DirectShow. Его нужно запускать из командной строки, а в качестве аргумента ему передавать имя воспроизводимого файла. Здесь так же сначала создаётся консольное приложение, а затем появляется дополнительное окно с воспроизводимым видео или статическим изображением. Если воспроизводить только звуковой файл, то никаких дополнительных окон не появляется.

Код: Выделить всё

#include "stdafx.h"
#include <control.h>

struct _CO_INITIALIZE
{
	_CO_INITIALIZE()
	{
		::CoInitialize(NULL);
	}
	~_CO_INITIALIZE()
	{
		::CoUninitialize();
	}
} co_init;

int _tmain(int argc, _TCHAR* argv[])
{ 
	if (argc < 2)
	{
		// Не указано имя файла...
		return -1;
	}

	CComPtr<IMediaControl> pFilGraph;
	pFilGraph.CoCreateInstance(__uuidof(FilgraphManager));
	if (pFilGraph != NULL)
	{
		// Загрузка файла...
		CComPtr<IFilterInfo> pFilInfo;
		pFilGraph->AddSourceFilter(CComBSTR(argv[1]), (LPDISPATCH*)&pFilInfo);
		if (pFilInfo != NULL)
		{
			CComPtr<IAMCollection> pCollection;
			pFilInfo->get_Pins((LPDISPATCH*)&pCollection);
			if (pCollection != NULL)
			{
				LONG nCount = 0;
				pCollection->get_Count(&nCount);
				for (int n = 0; n < nCount; n++)
				{
					CComPtr<IPinInfo> pPinInfo;
					pCollection->Item(n, (LPUNKNOWN*)&pPinInfo);
					if (pPinInfo != NULL)
					{
						pPinInfo->Render();
					}
				}
			}

			// Воспроизведение
			pFilGraph->Run();

			// Ожидание завершения...
			long lEvCode = 0;
			CComQIPtr<IMediaEvent> pEvent = pFilGraph;
			if (pEvent != NULL)
			{
				pEvent->WaitForCompletion(INFINITE, &lEvCode);
			}
		}
	}
	//
	return 0;
}

Для компиляции этого кода на Visual C++ необходимо создать проект консольного приложения (Win32 Console Application) и включить в нём опцию использования библиотек ATL.
При необходимости можно добавить в код вывод сообщений об ошибках.
Nebesny
Сообщения: 4
Зарегистрирован: 29 янв 2015, 19:33

WinMain писал(а):Ниже приведён пример кода простейшего консольного медиа-проигрывателя, который использует Windows-платформу DirectShow. Его нужно запускать из командной строки, а в качестве аргумента ему передавать имя воспроизводимого файла. Здесь так же сначала создаётся консольное приложение, а затем появляется дополнительное окно с воспроизводимым видео или статическим изображением. Если воспроизводить только звуковой файл, то никаких дополнительных окон не появляется.

Код: Выделить всё

#include "stdafx.h"
#include <control.h>

struct _CO_INITIALIZE
{
	_CO_INITIALIZE()
	{
		::CoInitialize(NULL);
	}
	~_CO_INITIALIZE()
	{
		::CoUninitialize();
	}
} co_init;

int _tmain(int argc, _TCHAR* argv[])
{ 
	if (argc < 2)
	{
		// Не указано имя файла...
		return -1;
	}

	CComPtr<IMediaControl> pFilGraph;
	pFilGraph.CoCreateInstance(__uuidof(FilgraphManager));
	if (pFilGraph != NULL)
	{
		// Загрузка файла...
		CComPtr<IFilterInfo> pFilInfo;
		pFilGraph->AddSourceFilter(CComBSTR(argv[1]), (LPDISPATCH*)&pFilInfo);
		if (pFilInfo != NULL)
		{
			CComPtr<IAMCollection> pCollection;
			pFilInfo->get_Pins((LPDISPATCH*)&pCollection);
			if (pCollection != NULL)
			{
				LONG nCount = 0;
				pCollection->get_Count(&nCount);
				for (int n = 0; n < nCount; n++)
				{
					CComPtr<IPinInfo> pPinInfo;
					pCollection->Item(n, (LPUNKNOWN*)&pPinInfo);
					if (pPinInfo != NULL)
					{
						pPinInfo->Render();
					}
				}
			}

			// Воспроизведение
			pFilGraph->Run();

			// Ожидание завершения...
			long lEvCode = 0;
			CComQIPtr<IMediaEvent> pEvent = pFilGraph;
			if (pEvent != NULL)
			{
				pEvent->WaitForCompletion(INFINITE, &lEvCode);
			}
		}
	}
	//
	return 0;
}

Для компиляции этого кода на Visual C++ необходимо создать проект консольного приложения (Win32 Console Application) и включить в нём опцию использования библиотек ATL.
При необходимости можно добавить в код вывод сообщений об ошибках.

а поддерживает это все кодек VP8 и контейнер Webm?
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

а поддерживает это все кодек VP8 и контейнер Webm?
Всё должно заработать, если добавить в систему соответствующие компоненты WebM/VP8 для DirectShow.
Установщик называется WebM/VP8 DirectShow Filters installer.
Скачать можно отсюда http://code.google.com/p/webm/downloads/list
Nebesny
Сообщения: 4
Зарегистрирован: 29 янв 2015, 19:33

WinMain писал(а):Всё должно заработать, если добавить в систему соответствующие компоненты WebM/VP8 для DirectShow.
Установщик называется WebM/VP8 DirectShow Filters installer.
Скачать можно отсюда http://code.google.com/p/webm/downloads/list
Все скомпилил - работает.
Но как в отладке посмотреть какие видео-фреймы берет кодер, их длину?я просто хочу подсунуть свой сырой поток VP8, зная как идут фреймы и их длину, имея готовый контейнер.
Nebesny
Сообщения: 4
Зарегистрирован: 29 янв 2015, 19:33

WinMain писал(а):Всё должно заработать, если добавить в систему соответствующие компоненты WebM/VP8 для DirectShow.
Установщик называется WebM/VP8 DirectShow Filters installer.
Скачать можно отсюда http://code.google.com/p/webm/downloads/list
Все скомпилил, спасибо!
Вопрос в том, как получить доступ к массиву данных которые обрабатываются кодером??
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

Готового кода у меня нет, к сожалению. Да и тема уж слишком специфическая, не для обсуждения на таком форуме. Но в двух словах это будет примерно так: тебе нужно научиться непосредственно работать с компонентами DirectShow (так называемыми фильтрами).
При загрузке медиа-файла платформа DirectShow динамически создаёт для него нужную топологию из медиа-фильтров и формирует связи между ними. Наглядно это можно увидеть с помощью приложения GraphEdit, который входит в состав Windows SDK. (На компьютере он расположен примерно так: C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin)
С помощью этого приложения можно визуально определить, какой из фильтров за что отвечает, т.е. их функциональное назначение. Таким образом из собственной программы можно непосредственно обратиться к нужному фильтру и получить от него нужные данные.
Но сразу предупреждаю: это задача не для новичков, если найдёшь в сети готовые примеры кода, то считай что тебе повезло.


P. S. Вместо платформы DirectShow можно использовать более современную платформу Microsoft Media Foundation (MMF). В ней имеется такой интерфейс как IMFSourceReader, который вполне самодостаточный для чтения медиа-файлов и получения из них потока в виде сэмплов аудио и видео. Так что он тебе вполне подойдёт. Но платформа MMF не работает на Windows XP, для неё требуется ОС Windows 7 и выше.
Ответить