Запись изображения и звука в avi файл, с помощью API MS Windows (комментарии)
Это сообщение сгенерировано автоматически.
Еще интересно было бы рассказать о записи отдельных кадров.
Вот это http://www.gamedev.ru/flame/forum/?id=95416 было сделано с помощью AviCap отдельными кадрами. Может кому-то пригодиться
Booster
Спасибо... Интересно... Хотя не нуждаюсь в данный момент в таком, но на будущее учту с чего начать... :)
libavcodec круче.
//Если предыдущий вызов AVIStreamSetFormat завершился неудачей, //то пытаемся установить другой формат. 16 бит на пиксель. bi.bmiHeader.biBitCount = 16; if(AVIERR_OK==AVIMakeCompressedStream( ppCompressedStreamVideo, pStreamVideo, pVideoOptions, NULL) ) { //Устанавливаем формат. if ( AVIERR_OK == AVIStreamSetFormat( *ppCompressedStreamVideo, 0, &bi, ( ( LPBYTE)pBits) - ( ( LPBYTE) &bi))) return true; //В случае неуспеха удаляем поток. AVIStreamRelease( *ppCompressedStreamVideo); pCompressedStreamVideo = 0; } //Если предыдущий вызов AVIStreamSetFormat завершился неудачей, //то пытаемся установить другой формат. 8 бит на пиксель. bi.bmiHeader.biBitCount = 8; if( AVIERR_OK==AVIMakeCompressedStream( ppCompressedStreamVideo, pStreamVideo, pVideoOptions, NULL) ) { //Устанавливаем формат. if ( AVIERR_OK == AVIStreamSetFormat( *ppCompressedStreamVideo, 0, &bi, ( ( LPBYTE)pBits) - ( ( LPBYTE) &bi))) return true; //В случае неуспеха удаляем поток. AVIStreamRelease( *ppCompressedStreamVideo); pCompressedStreamVideo = 0; }
если мы это делаем, то мы должны и позаботится о буфере который мы пишем, а в примере:
const DWORD sizeVideoFrame = WidthFrame * HeightFrame * 3; void *pVideo = malloc(sizeVideoFrame + sizeof( BITMAPINFOHEADER)); BITMAPINFOHEADER *pBitm = ( BITMAPINFOHEADER*)pVideo; ZeroMemory( pBitm, sizeof( BITMAPINFOHEADER)); pBitm->biWidth = WidthFrame; pBitm->biHeight = HeightFrame; pBitm->biBitCount = 24; pBitm->biPlanes = 1; pBitm->biSize = sizeof( BITMAPINFOHEADER); pBitm->biCompression = BI_RGB; pBitm->biSizeImage = sizeVideoFrame; char *pBits = ( char*)pVideo + sizeof( BITMAPINFOHEADER); int CountSoundInFrame = wf.nAvgBytesPerSec / FrameRate; DWORD *pSound = ( DWORD*)malloc( CountSoundInFrame); printf( "Recording "); for ( int i = 0; i<CountFrames; i++) { //Video frame for ( int i2 = 0; i2<( WidthFrame * HeightFrame); i2++) { unsigned int color = ( ( ( float)rand( ))/RAND_MAX)*0xffffff; pBits[i2*3] = ( ( char*)&color)[0]; pBits[i2*3+1] = ( ( char*)&color)[1]; pBits[i2*3+2] = ( ( char*)&color)[2]; } //Audio frame for ( int i3=0; i3<CountSoundInFrame/4; i3++) { unsigned short x = ( ( ( float)rand( ))/RAND_MAX)*AmplitudeSound; unsigned short y = ( ( ( float)rand( ))/RAND_MAX)*AmplitudeSound; ( ( WORD*)pSound)[i3*2] = x; ( ( WORD*)pSound)[i3*2+1] = y; } if ( !WriteFrameVideoCompress( pCompressedStreamVideo, ( BITMAPINFO*)pBitm, i)) break; if ( !WriteFrameAudio( pStreamAudio, pSound, CountSoundInFrame, i)) break; if ( !( i%FrameRate)) printf( "."); }
этого не делают, что неверно. Чтобы убедится в этом достаточно поменять
pBits[i2*3] = (( char*)&color)[0]; pBits[i2*3+1] = ( ( char*)&color)[1]; pBits[i2*3+2] = ( ( char*)&color)[2];
на
pBits[i2*3] = 0; pBits[i2*3+1] = 0; pBits[i2*3+2] = (( char*)&color)[2];
т.е. попытаться получить только "красный шум", и поэксперементировать с компрессорами. Например для Microsoft RLE будет НЕ красный шум. Попробуйте.
Так же утверждение в статье в пункте 7. Запись видео данных:
>>lpBuffer - указатель на буфер с данными кадра. Обратите внимание, что впереди этих данных обязательно должен быть корректно заполненный заголовок BITMAPINFOHEADER, иначе запись не произойдёт.
Неверно. Не должен там быть BITMAPINFOHEADER. Достаточно только указатель на буфер с самими данными, и размер этого самого буфера, НО буфер должен АБСОЛЮТНО соответствовать формату который мы выставили в пункте 5. Создание видео потока с компрессией через AVIStreamSetFormat.
Тема в архиве.