Форум: "Media";
Текущий архив: 2004.01.05;
Скачать: [xml.tar.bz2];
ВнизПроблема при компрессии MPEG layer-3 Найти похожие ветки
← →
Verg (2003-09-02 11:23) [0]При компрессии указанным кодеком возникла проблема
acmStreamConver вызывает Invalid floating point operation в двух случаях:
1. Если исходный буфер содержит одни нули (тишина)
2. На последнем блоке преобразования, т.е. когда
ConvertFlags=ACM_STREAMCONVERTF_END;
Ничего понять не могу.
Когда сигнал осмысленный - работает без проблем. Однако последнее преобазование всеравно выдает IFPO.
С другими кодеками таких проблем не возникало.
Ни кто не знает в чем может быть дело? Что надо проверить? Хотя бы приблизитьельно.
← →
Крот (2003-09-02 11:35) [1]А через DirectShow не пробовал?
← →
Verg (2003-09-02 11:40) [2]
> А через DirectShow не пробовал?
Нет не пробовал.
← →
Verg (2003-09-02 12:40) [3]Кстати, эффект проявляется только при стереосигнале. Если канал сжатия один - все идет как надо.
← →
Крот (2003-09-02 16:43) [4]А можно немного поподробнее, то есть надо сконверитровать существующий файл (скажем, WAV) в MPEG3? Или поступает звук со входа?
← →
Verg (2003-09-03 08:37) [5]Да, есть поток в формате PCM, его надо преобразовать в один из компрессированных форматов (wav) из имеющихся в системе (установленных кодеков). Для этого я воспользовался штатным средством компресии в Windows - ACM. А точнее функциями acmSTREAM***.
Вот. И все компрессоры нормально работают, кроме MPEG Layer-3.
Этот при получении на вход порции данных содержащих одни нули (математический ноль, а не шумы сигнала) в стереосигнале (2 канала) и только в стереосигнале, вырабатывает исключение IFPO.
Кроме того, IFPO в этом случае он вырабатывает на любую порцию стереосигнала обозначенную в fdwConvert ACM_STREAMCONVERTF_END, т.е. на последнюю.
Если поставить acmSTREAMConvert в блок try except end, то при записи реального сигнала (имеющего в паузах шум, а не мат0) создается впечатление, что все нормально, файл получается, декодируется любым софтом, но последняя порция сигнала просто отсутствует. Тогда я стал разбираться. Навходе компрессора занулил поступающий поток и увидел, что выходного потока просто НЕТ. Оказалось то, о чем я писал раньше. Вот сижу теперь почти наугад проверяю всевозможные даже невероятные версии. Хотя кажется, что ошибка (или нехватка информации) должна быть простой и лежать на поверхности...
← →
Verg (2003-09-03 08:42) [6]Да, то, что я считаю это моей ошибкой, а не глюком кодека основано на том, что SoundForge прекрасно записывает wav-ки в этом формате. Специально в нем синтезировал mute-сигнал на два канала и записывал в формате MPEG layer-3. Все SF записывает прекрасно, потом считывает и считывает сигнал той длительности, которую я изначально синтезировал.
← →
Verg (2003-09-03 11:58) [7]Ну вот уже упростил до "безобразия".
Что же не так?
unit AcmMp3;
interface
function TryToCompressMP3:boolean;
implementation
uses Windows,SysUtils,MmSystem,MSACM;
const
WAVE_FORMAT_MPEG_LAYER3 = $55;
function TryToCompressMP3:boolean;
var Hdr : TACMSTREAMHEADER;
Tdtl: TACMFORMATTAGDETAILS;
WfSrc : TWaveFormatEx;
Wf : PWaveFormatEx;
Handle : HACMSTREAM;
DstBuffer,
Buffer : pchar;
BufferSize,
DstBuffSize : DWORD;
ConvertFlags : DWORD;
begin
result:=false;
// Заполняем заголовок псевдопотока
WfSrc.wFormatTag:=WAVE_FORMAT_PCM;
WfSrc.nChannels:=2; // Стерео
WfSrc.nSamplesPerSec:=8000;
WfSrc.wBitsPerSample:=16;
WfSrc.nBlockAlign:=WfSrc.nChannels*(WfSrc.wBitsPerSample div 8);
WfSrc.nAvgBytesPerSec:=WfSrc.nSamplesPerSec*WfSrc.nBlockAlign;
WfSrc.cbSize:=0;
FillChar(Tdtl, sizeof(Tdtl), 0);
Tdtl.cbStruct := sizeof (Tdtl);
Tdtl.dwFormatTag:=WAVE_FORMAT_MPEG_LAYER3;
Wf:=nil;
// Попросим у ACM размер формата данного типа
try
if acmFormatTagDetails(0, Tdtl, ACM_FORMATTAGDETAILSF_FORMATTAG)=MMSYSERR_NOERROR then
begin
Wf:=AllocMem(Tdtl.cbFormatSize);
Wf^.wFormatTag:=WAVE_FORMAT_MPEG_LAYER3;
// заполним Wf^ параметрами целевого формата
if acmFormatSuggest(0, WfSrc, Wf^, Tdtl.cbFormatSize, ACM_FORMATSUGGESTF_WFORMATTAG)<>MMSYSERR_NOERROR then exit;
end else abort;
BufferSize:=WfSrc.nBlockAlign*1024;// Ну например на 1024
Buffer:=AllocMem(BufferSize);
try
if acmStreamOpen(@Handle, 0, WfSrc, Wf^, nil, 0, 0,0)<>MMSYSERR_NOERROR then exit;
try
// Узнаем какой потребуется буфер выходного потока, для данного входного
if acmStreamSize(Handle, BufferSize, DstBuffSize, ACM_STREAMSIZEF_SOURCE)<>MMSYSERR_NOERROR then exit;
DstBuffer:=AllocMem(DstBuffSize);
try
ConvertFlags := ACM_STREAMCONVERTF_START or ACM_STREAMCONVERTF_BLOCKALIGN;
FillChar(Buffer^, BufferSize,0); // Закладываем во входном буфере одни нули
//Заполняем заголовок входного буфера потока ACM
FillChar(Hdr, sizeof(Hdr),0);
Hdr.cbStruct:=Sizeof(Hdr);
Hdr.pbSrc:=pbyte(Buffer);
Hdr.cbSrcLength:=BufferSize;
Hdr.pbDst:=pbyte(DstBuffer);
Hdr.cbDstLength:=DstBuffSize;
if acmStreamPrepareHeader(Handle, Hdr, 0)<>MMSYSERR_NOERROR then exit;
if acmStreamConvert(Handle, Hdr, ConvertFlags)<>MMSYSERR_NOERROR then exit;
if acmStreamUnPrepareHeader(Handle, Hdr, 0)<>MMSYSERR_NOERROR then exit;
result:=true;
finally
FreeMem(DstBuffer);
end;
finally
acmStreamClose(Handle,0);
end;
finally
Freemem(Buffer);
end;
finally
if Wf<>nil then FreeMem(Wf);
end;
end;
end.
← →
Verg (2003-09-03 12:47) [8]Во дурь-то...
Оказывается
1. Размер входного буфера не должен превосходить 512 отсчетов
2. Размер входного буфера на последнее преобразование должен быть =0
О как!
Страницы: 1 вся ветка
Форум: "Media";
Текущий архив: 2004.01.05;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.013 c