Я пытаюсь написать приложение Delphi 6, которое принимает видео и аудио и записывает их в AVI с помощью служб VFW. Мне удалось наладить работу видеопотока. Он отлично работает в VLC или Windows Media Player. Но когда я затем добавляю аудиопоток и пытаюсь воспроизвести выходной AVI, проигрыватель VLC жалуется на то, что файл AVI поврежден. Он воспроизведет файл, и видео выглядит нормально, но нет звука. Я пробовал добавить аудиопоток перед записью видеопотока, а затем после него. Ни то, ни другое не сработало.
Кроме того, если я не добавляю аудиопоток, я могу щелкнуть правой кнопкой мыши выходной файл AVI в проводнике Windows, и на вкладке сводки я могу увидеть правильную информацию для видеоданных в потоке. После добавления потока щелчок правой кнопкой мыши вместо этого отображает сообщение о состоянии, в котором говорится, что свойства AVI не могут быть прочитаны.
ОБНОВЛЕНИЕ: я делаю что-то в корне неправильно. Оказывается, что-то, что я делаю, - это выдуваю заголовок верхнего уровня файла. Если я не создаю аудиопоток, с файлом все в порядке, и я вижу обычную информацию заголовка в самом начале файла. В тот момент, когда я вызываю для создания аудиопотока второй поток, который я создаю, заголовок в самом начале выходного файла AVI становится полностью пустым (нули). Даже если я не делаю вызов AVIStreamSetFormat () или запись любых данных (и даже если я это сделаю), просто делая этот второй вызов AVICreateStream () стирает самое начало файла при проверке файла с помощью шестнадцатеричного редактора. Что я мог делать, чтобы вызвать такую сумму, если "повредил" выходной файл.
Мой вопрос:
1) Что я делаю не так? 2) Знаете ли вы хороший образец, который показывает, как создать AVI с чередованием аудио и видео, особенно тот, который показывает, как писать сжатый аудиопоток?
Вот код, который я использую для записи аудиопотока после того, как полностью записал видеопоток. В переменной уровня единицы измерения FAvi уже заполнено поле TWaveFormatEx (wfx). Я проверил содержимое, и все поля установлены на допустимые значения: частота дискретизации 8000 кГц, 1 канал, 16 бит на канал и тег формата 1 (WAVE_FORMAT_PCM). Выравнивание блоков, скорость передачи данных и т. Д. Также правильно заполнены:
function TAviWriterWithCompression.addAudioFrame(dat: Pointer; numbytes: Cardinal): HRESULT;
var
bRetErr: boolean;
numsamps: LongInt;
ahdr: TAVISTREAMINFO;
hr: HRESULT;
lSampWritten, lBytesWritten: LONG;
begin
Result := S_OK;
bRetErr := true;
if Assigned(FAvi_) then
begin
if Assigned(dat) and (numbytes <> 0) then
begin
if not FAvi_.iserr then
begin
if FAvi_.wfx.nChannels <> 0 then
bRetErr := false
else
Result := LongInt(AVIERR_BADFORMAT);
end
else
Result := LongInt(AVIERR_ERROR);
end
else
Result := LongInt(AVIERR_BADPARAM);
end
else
Result := LongInt(AVIERR_BADHANDLE);
if bRetErr then
// =========================== EXIT POINT ==============
exit;
if FAvi_.wfx.wBitsPerSample <= 0 then
begin
Result := LongInt(AVIERR_BADFORMAT);
// =========================== EXIT POINT ==============
exit;
end; // if FAvi_.wfx.wBitsPerSample <= 0 then
numsamps := Trunc((numbytes * 8) / FAvi_.wfx.wBitsPerSample);
if ((numsamps * FAvi_.wfx.wBitsPerSample / 8) <> numbytes) then
begin
Result := LongInt(AVIERR_BADPARAM);
// =========================== EXIT POINT ==============
exit;
end; // if ((numsamps * FAvi_.wfx.wBitsPerSample/8) <> numbytes) then
if not Assigned(FAvi_.theAs) then
begin
ZeroMemory(@ahdr, sizeof(ahdr));
ahdr.fccType := streamtypeAUDIO;
ahdr.dwScale := FAvi_.wfx.nBlockAlign;
ahdr.dwRate := FAvi_.wfx.nSamplesPerSec*FAvi_.wfx.nBlockAlign;
ahdr.dwSampleSize := FAvi_.wfx.nBlockAlign;
ahdr.dwQuality := DWORD(-1);
hr := AVIFileCreateStream(FAvi_.pfile, FAvi_.theAs, ahdr);
if hr <> AVIERR_OK then
begin
Result := hr;
// Set the error flag.
FAvi_.iserr := true;
// =========================== EXIT POINT ==============
exit;
end; // if hr <> AVIERR_OK then
hr := AVIStreamSetFormat(FAvi_.theAs, 0, @FAvi_.wfx, sizeof(FAvi_.wfx));
if hr <> AVIERR_OK then
begin
Result := hr;
// Set the error flag.
FAvi_.iserr := true;
// =========================== EXIT POINT ==============
exit;
end; // if hr <> AVIERR_OK then
end; // if not Assigned(FAvi_.theAs) then
// now we can write the data
hr := AVIStreamWrite(FAvi_.theAs, FAvi_.nsamp, numsamps, dat, numbytes, AVIIF_KEYFRAME, @lSampWritten, @lBytesWritten);
if hr <> AVIERR_OK then
begin
Result := hr;
// Set the error flag in our utility object.
FAvi_.iserr := true;
// =========================== EXIT POINT ==============
exit;
end; // if hr <> AVIERR_OK then
Inc(FAvi_.nsamp, numsamps);
// Set the flag that tells it is no longer a virgin file and that
// attempting to set the compression is not allowed.
FIsVirginFile := false;
end;
Вот код, который очищает аудио- и видеопоток при завершении:
destructor TAviWriterWithCompression.Destroy;
begin
// Code goes here.
if Assigned(FAvi_) then
begin
// Release the streams.
if Assigned(FAvi_.theAs) then
begin
AVIStreamRelease(FAvi_.theAs);
FAvi_.theAs := nil;
end;
if Assigned(FAvi_.thePsCompressed) then
begin
AVIStreamRelease(FAvi_.thePsCompressed);
// FAvi_.thePsCompressed := nil;
end;
if Assigned(FAvi_.thePs) then
begin
AVIStreamRelease(FAvi_.thePs);
// FAvi_.thePs := nil;
end;
if Assigned(FAvi_.pfile) then
begin
AVIFileRelease(FAvi_.pfile);
// FAvi_.pfile := nil;
end;
AVIFileExit();
// FreeAndNil(FAvi_);
end; // if Assigned(FAvi_) then
inherited Destroy;
end;
Уведомить: @RemyLebau
VirtualDub
должен показать вам (не только), как обрабатывать аудио потоки и правильно настройте все структуры (см. AudioSource.cpp, InputFileMP3.cpp и InputFileWAV.cpp). Я был доволен этим несколько лет назад, когда пользовался им. - person TLama   schedule 07.05.2012