2016-10-25 9 views
0

У меня есть анимация/спрайт, созданный с использованием SDL2. Анимация отлично работает, когда она отображается на экране. Но теперь я также хочу, чтобы это было записано в видеофайл (локально сохраненный). Для этого я планирую использовать API-интерфейсы FFmpeg, к которым я отправлю необработанный массив данных пикселей RGB.SDL2 C++ Capturing Video of Renderer Animation/Sprite

Проблема с извлечением данных из API SDL2.

То, что я попытался это:

// From http://stackoverflow.com/questions/30157164/sdl-saving-window-as-bmp 
SDL_Surface *sshot = SDL_CreateRGBSurface(0, 750, 750, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); 
SDL_RenderReadPixels(gRenderer, NULL, SDL_PIXELFORMAT_ARGB8888, sshot->pixels, sshot->pitch); 

// From https://wiki.libsdl.org/SDL_RWFromMem 
char fName[50]; 
sprintf(fName, "/tmp/a/ss%03d.bmp", fileCnt); 


char bitmap[310000]; 
SDL_RWops *rw = SDL_RWFromMem(bitmap, sizeof(bitmap)); 
SDL_SaveBMP_RW(sshot, rw, 1); 

Выше не работает. Но демпинг один кадр в файл со следующим кодом работает:

SDL_SaveBMP(sshot, "/tmp/alok1/ss.bmp")

Это, очевидно, не является приемлемым решением - Дать тысячи КМБ, а затем с помощью FFmpeg из командной строки для создания видео.

Что я делаю неправильно? Как вы извлекаете данные из SDL_RWops? Является ли использование SDL_RWFromMem правильным подходом к моей проблеме?

+2

'750 * 750 * 4' больше, чем' 310000'. Ваш буфер слишком мал. (вам потребуется ширина 'width * height * bpp' + байтов заголовка BMP, по крайней мере) – keltar

+0

Да, вы правы. Большое спасибо за указание на это. Я подсчитал, что он близок к 2.5 МБ, и, чтобы быть в безопасности, я хотел выделить 3 МБ. Пропустил нуль. Я могу принять это как ответ, если вы опубликуете его как таковой. Если вы считаете, что это слишком тривиально, я удалю вопрос. Еще раз спасибо! – alok

ответ

1

Ваш буфер слишком мал, чтобы соответствовать указанному изображению, поэтому его нельзя сохранить здесь. Увеличьте размер буфера, по крайней мере, до фактического размера изображения + заголовок BMP (width*height*bpp + 54, но нужно также подсчитать заполнение (что означает SDL_Surface как pitch)).

Обратите внимание, что прием 3 Мб из стека может привести к опасному приближению к переполнению (но все равно может быть и в порядке, в зависимости от того, что произошло в функциях до того, что было сказано). Цепочка вызова нескольких функций, которые берут большой кусок стека, может очень быстро истощить его. Вероятно, вам совсем не нужно дополнительное пространство или преобразование BMP вообще - например, создание AVImage и копирование пикселей непосредственно на него с SDL_Surface.

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

+0

Благодарим вас за дополнительную рекомендацию. Я сразу изменю размеры. Кроме того, я выделяю 3 МБ и освобождаю его после использования в цикле из однопоточного приложения. 3MB разрешено в моей среде, но может ли он все еще переполняться? Кроме того, после того, как все модули будут завершены, этот массив будет заменен одним из структурированных FFmpeg, как вы предложили. Большое спасибо! – alok

+0

Нет, если ваш стек равен, например. 4 Мб (или 8 на некоторых платформах), вы можете свободно использовать до этой суммы. Но если у вас есть функция, которая занимает несколько мегабайт стека и вызывает другую функцию, которая вызывает другую функцию, ..., каждый из которых принимает большие массивы в стеке - он может переполняться (рекурсивные функции управляют переполнением даже при распределении крошечной суммы, но с огромным количеством вложенных вызовов). Но вы знаете свой код лучше, если это не так, и эта функция не называется глубоко в цепочке вызовов, тогда она может быть полностью в порядке. – keltar

+0

Мне нужно какое-то время, чтобы обработать это, исходя из фона Java, и точно не справиться с этим :) Я лучше ознакомлю это с экспертом. Еще раз спасибо всем за помощь. – alok