Чтение и запись видеофреймов с помощью Dll FFmpeg / FFmpeg / Recog.ru - Распознавание образов для программистов


Чтение и запись видеофреймов с помощью Dll FFmpeg

Пользуясь описанием http://recog.ru/blog/ffmpeg/67.html и http://recog.ru/blog/ffmpeg/66.html можно создать библиотеку Dll с нужными функциями. Для начала мы попробуем как записывать и читать видеофреймы, а для этого используем наработки из OpenCV. Для этого при компиляции нам необходимо будет включить код из файлов OpenCV:
cap_ffmpeg_impl.hpp
cap_ffmpeg_api.hpp
ffmpeg_codecs.hpp
А откомпилировать можно примерно так:
set path=C:\MinGW\bin;%path% & gcc -Wall -shared -o ffmpeg.dll -O2 -x c++ -I../include out_dll.c -L../lib -lavformat -lavcodec -lavdevice -lswscale -lavutil -lwsock32
После этого ffmpeg.dll будет готова. С ее помощью можно будет читать и записывать видеофреймы так, как продемонстрировано в примере ниже:
#include <windows.h>
#include <stdio.h>

#ifndef MKTAG
#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
#endif

typedef void Capture;
typedef unsigned char* Image;
typedef void VWriter;

Capture* (__cdecl *cvCreateFileCapture_FFMPEG)(const char*);	
int (__cdecl *cvGrabFrame_FFMPEG)(Capture*);
int (__cdecl *cvRetrieveFrame_FFMPEG)(Capture*,unsigned char** data,int* step, int* width, int* height, int* cn);
void (__cdecl *cvReleaseCapture_FFMPEG)(Capture**);
VWriter* (__cdecl *cvCreateVideoWriter_FFMPEG)(const char* filename,
            int fourcc, double fps, int width, int height, int isColor );
int(__cdecl *cvWriteFrame_FFMPEG)(VWriter*, const unsigned char* data,
                           int step, int width, int height, int cn, int origin);
void (__cdecl *cvReleaseVideoWriter_FFMPEG)(VWriter**);

int main(int argc, char* argv[])
{
	if (argc < 2) return 1;

	// Открытие входного видеофайла
	HINSTANCE dllInstance=LoadLibrary("ffmpeg.dll");
	(FARPROC&)cvCreateFileCapture_FFMPEG=GetProcAddress(dllInstance,"cvCreateFileCapture_FFMPEG");
	(FARPROC&)cvGrabFrame_FFMPEG=GetProcAddress(dllInstance,"cvGrabFrame_FFMPEG");
	(FARPROC&)cvRetrieveFrame_FFMPEG=GetProcAddress(dllInstance,"cvRetrieveFrame_FFMPEG");
	(FARPROC&)cvReleaseCapture_FFMPEG=GetProcAddress(dllInstance,"cvReleaseCapture_FFMPEG");
	(FARPROC&)cvCreateVideoWriter_FFMPEG=GetProcAddress(dllInstance,"cvCreateVideoWriter_FFMPEG");
	(FARPROC&)cvWriteFrame_FFMPEG=GetProcAddress(dllInstance,"cvWriteFrame_FFMPEG");
	(FARPROC&)cvReleaseVideoWriter_FFMPEG=GetProcAddress(dllInstance,"cvReleaseVideoWriter_FFMPEG");

	Capture* cap = cvCreateFileCapture_FFMPEG(argv[1]);
	if (cap==0) return 2;

	bool begin=0;
	int frames = 0;
	VWriter* writer=0;
	// Цикл перебора фреймов и записи их
	for(;;)
	{
		int r=cvGrabFrame_FFMPEG(cap);
		if (!r) break;
		Image Img=0;
		int step,width,height,cn;
		r=cvRetrieveFrame_FFMPEG(cap,&Img,&step,&width,&height,&cn);
		if (!r) break;
		if (!begin)
		{
			begin=1;
			printf("Video - Width(%d), Height(%d)\n",width,height);
			writer=cvCreateVideoWriter_FFMPEG("out.avi",MKTAG('D', 'I', 'V', '3'),30,width,height,true);
		}
		if (writer!=0)
			cvWriteFrame_FFMPEG(writer,Img,step,width,height,cn,0);
		printf(".");
		frames++;
	}
	printf("\nAll frames = %d", frames);
	cvReleaseCapture_FFMPEG(&cap);
	if (writer!=0) cvReleaseVideoWriter_FFMPEG(&writer);
	Sleep(5000);
	return 0;
}

Вкратце прокомментирую. Нам не нужно работать со структурами видеопотоков, а достаточно будет указателей на память, поэтому потоки объявляем как void. Далее описаны заголовки используемых функций.
В главной функции динамически подгружается библиотека и устанавливаются адреса функций. Затем открывается видеопоток на существующий видеофайл с помощью cvCreateFileCapture_FFMPEG. И далее осуществляется перебор всех фреймов с помощью функций cvGrabFrame_FFMPEG и cvRetrieveFrame_FFMPEG. На первом фрейме создается поток записи в out.avi с помощью cvCreateVideoWriter_FFMPEG. Ну а каждый кадр пишется с помощью cvWriteFrame_FFMPEG. В конце потоки освобождаются. В общем принцип работы, как в OpenCV. И такой же недостаток – отсутствует звуковая дорожка. Об этом мы возможно поговорим в следующий раз.
  • 0
  • 11 июля 2012, 14:49
  • vidikon

Комментарии (0)

RSS свернуть / развернуть

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.