Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.16;
Скачать: CL | DM;

Вниз

Разделение аудио потоков в AVI   Найти похожие ветки 

 
Noby   (2006-01-30 14:07) [0]

Подскажите, пожалуйста. Каким образом можно в своей программе не используя компонентов разделить аудио потоки в avi  файлах и воспроизводить только тот, который нужен?
Нужен код. Заранее  спасибо!


 
NailMan ©   (2006-01-30 16:41) [1]

Уточни исходные данные.
1. Воспроизводишь чем? DirectShow?
2. Как я понял у видео несколько дорожек. Тебе надо воспроизводить одну из них вместе с видео? или только аудио?

---
P.L.U.R. and WBR, NailMan aka 2:5020/3337.13


 
Noby   (2006-01-30 16:58) [2]

1. Да через DirectShow.
2. И Видео и аудои


 
NailMan ©   (2006-01-30 21:11) [3]

Ну тады все просто:

Procedure TVideoEngine.SetMultipleVolume(vLevel:integer);
var
   pEnum : IEnumFilters;
   pFilter :IBaseFilter;
   cFetched : dword;
   CL:TGUID;
     i:integer;
     BA : IBasicAudio;
     z : integer;
begin
i:=0;
repeat
   // Get filter enumerator
   dsGraphBuilder.EnumFilters(pEnum);
   while pEnum.Next(1, pFilter, @cFetched) = S_OK do
   begin
       pFilter.GetClassID(CL);
       if IsEqualGUID(CL,CLSID_DSoundRender) then
        begin
         If i<>CurrentPlayedAUDS then
          z:=AUDSVolume[i]
         else
          z:=vLevel;

          pFilter.QueryInterface(IID_IBasicAudio,BA);
          BA.put_Volume(VolumeTable[z]);
          AUDSVolume[i]:=z;
          BA:=nil;
          inc(i);
        end;
       pFilter:=nil;
   end;
   pFilter:=nil;
   pEnum:=nil;
until dword(i)=avi.audstreams;
end;


В данном случае здесь несколько расширенная функция установки громкости звуковых  дорожек.
vLevel - уровень матер-дорожки(которая выбрана пользователем, ее номер CurrentPlayedAUDS).
AUDSVolume - это массив уровней громкости(0..16) всех дорожек в файле.
VolumeTable - массив-константа в которой хранятся реальные значения уровней громкости которые принимает DShow. Содержимое константы:
VolumeTable      : Array[0..16]  of Integer = (-10000,-9000,-7500,-6500,-5500,-4500,-4000,-3000,-2000,-1000,-750,-500,-250,-125,-100,-50,0);

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

         If i<>CurrentPlayedAUDS then
          z:=AUDSVolume[i]
         else
          z:=vLevel;


сделать

         If i<>CurrentPlayedAUDS then
          z:=-10000
         else
          z:=vLevel;


Ну и соотвественно лишнее поудалять из тела процедуры.

---
P.L.U.R. and WBR, NailMan aka 2:5020/3337.13


 
Noby   (2006-01-31 14:13) [4]

Только, я вот одного не понял что вот это такое dword(i)=avi.audstreams;? с чем его есть то...


 
NailMan ©   (2006-01-31 15:29) [5]

Ну подчистить надо обязательною писалась процедура очень давно и частично не мной.

собсно, зачем добавил проверку на количество аудиорендереров не помню, был какой-то закидон, вот и добавил. Выброси если без этого работает.

---
P.L.U.R. and WBR, NailMan aka 2:5020/3337.13


 
Noby   (2006-01-31 16:01) [6]

псиб:), а возможно ли определинть сколько аудио дорожек в файле? Предположим что пользователь не знает о том сколько там дорожек.


 
Дима   (2006-01-31 22:26) [7]

я попробовал и у меня при смене воспроизводится отдельно только второе аудио а при переключении на первое воспроизводятся оба… что мне делать с этим как от этого избавиться?

С уважением Дима.


 
NailMan ©   (2006-01-31 23:10) [8]

Noby
можно узнать несколькими способами.

Самый простой(имея файлик типа DirectX9_c.chm из SDK где описаны структуры AVI-RIFF) - это распотрошить заголовок AVI-RIFF. там все структурированно описано что за потоки, каких форматов, кодеки(номера в случае аудио, чтобы узнать название надо энумератором по реесту поковырять, если надо могу дать процедурку ;-) ) и пр.

В заголовке еще много всякой полезной инфы выудить можно, включая все  кодеки всех потоков, длительности, частоты дискретизации, etc...

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

Function TVideoEngine.GetAudioTracks:Integer;
var
  pEnum : IEnumFilters;
  pFilter :IBaseFilter;
  cFetched : dword;
  CL:TGUID;
begin
result:=0;
  // Get filter enumerator
  dsGraphBuilder.EnumFilters(pEnum);
  while pEnum.Next(1, pFilter, @cFetched) = S_OK do
  begin
      pFilter.GetClassID(CL);
      if IsEqualGUID(CL,CLSID_DSoundRender) then  inc(Result);
      pFilter:=nil;
  end;
  pFilter:=nil;
  pEnum:=nil;
end;


Другими словами сколько аудиорендереров в графе, стока и дорожек ;-)

---
P.L.U.R. and WBR, NailMan aka 2:5020/3337.13


 
NailMan ©   (2006-01-31 23:14) [9]

Вот так попробуй:
Procedure TVideoEngine.SetMultipleVolume(TrackID:integer;vLevel:integer);
var
  pEnum : IEnumFilters;
  pFilter :IBaseFilter;
  cFetched : dword;
  CL:TGUID;
    BA : IBasicAudio;
    z : integer;
begin
repeat
  // Get filter enumerator
  dsGraphBuilder.EnumFilters(pEnum);
  while pEnum.Next(1, pFilter, @cFetched) = S_OK do
  begin
      pFilter.GetClassID(CL);
      if IsEqualGUID(CL,CLSID_DSoundRender) then
       begin
        If i<>TrackID then
         z:=-10000 else z:=vLevel;

         pFilter.QueryInterface(IID_IBasicAudio,BA);
         BA.put_Volume(VolumeTable[z]);
         BA:=nil;
       end;
      pFilter:=nil;
  end;
  pFilter:=nil;
  pEnum:=nil;
end;


значение массива VolumeTable тоже что и было.

Указываешь номер дороги и громкость, остальные глушатся в ноль. Алгоритм тут жесткий, что не наше, то глушим.

---
P.L.U.R. and WBR, NailMan aka 2:5020/3337.13


 
Noby   (2006-02-03 02:22) [10]

Дима

У меня та же проблема была… у меня нормально работает так: SetMultipleVolume(-1, 0). Глушатся только те что не должны работать, а воспроизведение сразу двух дорожек при этом не прослушивается :).
-1 это номер дорожки, а 0 глушим не нужное.


 
Noby   (2006-02-03 02:27) [11]

NailMan
Спасибо за инфу очень полезная для меня и нужная.

Есть еще один вопросик относительно звука… можно ли вывести выбранный звук в буфер и в последствии сохранить его отдельно от видео в любой выбранный пользователем формат?

Хотелось бы конечно выудить все инфу из файла но наверное мне не дано это сделать :( поскольку толком в сети я не смог талькового найти ничего


 
NailMan ©   (2006-02-03 11:22) [12]

Noby
> Есть еще один вопросик относительно звука… можно ли вывести
> выбранный звук в буфер и в последствии сохранить его отдельно
> от видео в любой выбранный пользователем формат?

Можно выдрать фреймы аудиодорог и собрать их в любой файл или по крайней мере в Wav, но для этого придется по любому растормошить заголовок AVI-RIFF, таблицу индексов в конце файла и потом по таблице разобрать всю секцию данных выдергивая фреймы. Тут нужно знать формат и структуру WAV(это вобщем-то тот же AVI-RIFF только упрощенный).

Чтобы конвертить в другие форматы(в т.ч. и сжатие), можно сделать свой граф на основе исходного, повыкидывать оттуда все ненужное и внедрить на место аудиорендерера кодек сжатия и вобщем-то неизвестный фильтр записи файла на диск или фильтр-заглушку с которой можно получить зажатый фрейм аудио и потом его записывать в нужный формат(*.mp3 например).

Вобщем в этом деле много сложностей. самое простое это просто вырезать дородку по фреймам и в wav слить, как я предложил в первом варианте. Так делает VirtualDub например.

---
P.L.U.R. and WBR, NailMan aka 2:5020/3337.13


 
Noby   (2006-02-04 05:22) [13]

Не думал что это такая трудоемкая работа :( Скинь плыз AVI-RIFF, попробую что сделать.

Спасибо и на этом


 
NailMan ©   (2006-02-04 13:28) [14]

Функция потрошения загововков AVI-RIFF(только модификаций AVI). Собрана с учетом нескольких модификаций структур заголовка, которые пользуют разные программы создания видео.
На выходе выходит заполненная структура, которая и используется далее для удобного выуживания нужной информации о файле.

В теле часто встречается ненужная строчка move(PD^,FCC,4); - это для того чтобы контролировать процесс навигации по секциям во время отладки парсинга нового вида заголовка(с какой-то левой неизвестной секцией). В целом прибить их можно или закоментить.


type
        FCC_Type = array[0..3] of char;
Const

        FCC_RIFF : FCC_Type = "RIFF";
        FCC_hdrl : FCC_Type = "hdrl";
        FCC_AVI  : FCC_Type = "AVI ";
        FCC_avih : FCC_Type = "avih";
        FCC_strl : FCC_Type = "strl";
        FCC_strh : FCC_Type = "strh";
        FCC_strf : FCC_Type = "strf";
        FCC_strd : FCC_Type = "strd";
        FCC_strn : FCC_Type = "strn";
        FCC_MOVI : FCC_Type = "movi";
        FCC_LIST : FCC_Type = "LIST";
        FCC_JUNK : FCC_Type = "JUNK";
        FCC_indx : FCC_Type = "indx";
        FCC_vids : FCC_Type = "vids";
        FCC_MPEG : FCC_Type = chr($0)+ chr($0) + chr($01)+ chr($BA);

TYPE
           TFOURCC = array[0..3] of char;    

           TVidsFormat = record
                 BMfmt : TBITMAPINFOHEADER;
                 DVFmt : TDVINFO;
           end;
          TVideoStream = record
                    st : TAVIStreamHeader;
                   FMT : TVidsFormat;
          end;

          TAudioStream = record
                    st : TAVIStreamHeader;
                WAVFmt : TWaveFormatEx;
          end;
                    TAviInfo = record
                   AVIHeader : TAVIMainHeader;
                  audstreams : DWORD;
                        vids : TvideoStream;
                        auds : Array[0..4] of TAudioStream;
                         CRC : Int64;
                    end;

   


Function ReadAVIHeader(Const FName:String;Var Avi:TAviInfo):Cardinal;
var f:Integer;
    p,PD:pointer;
    NulDD,i,leng:Cardinal;
audstreams:dword;
    FCC,FCC2 : Array[0..3] of char;
    MH : ^TAVIMainHeader;
    SH : ^TAVIStreamHeader;
   VFH : ^TVidsFormat;
   WVH : ^TWaveFormatEx;

begin
Result:=1; //По умолчанию - AVIVideo
Zeromemory(@AVi,sizeof(TAviInfo));

if FileAutoDetection then avi.CRC:=getfilecrc(fname);

F:=Fileopen(fname,fmopenread or fmsharedenynone);

 fileread(f,fcc,4);   //RIFF
 fileread(f,nuldd,4);
 fileread(f,fcc2,4);  //AVI_

 if (fcc=fcc_riff) and (fcc2<>FCC_AVI) then
  begin
    result:=0;
   Fileclose(F);
   exit;
  end;

 if (fcc<>fcc_riff) then
   begin
    If FCC=FCC_mpeg then result:=2
     else
     result:=0;
    Fileclose(F);
    exit;
   end;

 Fileread(f,fcc,4);  //LIST
 fileread(f,nuldd,4);
  getmem(p,nuldd+1024);
   fileread(f,p^,nuldd);
 fileclose(f);

 PD:=P; //stay on "hdrl"
 inc(DWORD(PD),4); //stay on "avih"
  MH:=PD;
  AVi.AVIHeader.dwMicroSecPerFrame:=MH^.dwMicroSecPerFrame;
  avi.AVIHeader.dwMaxBytesPerSec:=mh^.dwMaxBytesPerSec;
  avi.AVIHeader.dwFlags:=mh^.dwFlags;
  avi.AVIHeader.dwTotalFrames:=mh^.dwTotalFrames;
  avi.AVIHeader.dwStreams:=mh^.dwStreams;
 inc(DWORD(PD),sizeof(TAVIMainHeader)); //Stay on LIST
 audstreams:=0;
    move(PD^,FCC,4);
 For i:=0 to avi.AVIHeader.dwStreams-1 do
  Begin
   inc(DWORD(PD),4); //stay on "strl" length
    move(PD^,FCC,4);
   inc(DWORD(PD),4); //Stay on "strl"
    move(PD^,FCC,4);
   inc(DWORD(PD),4); //stay on "strh"
    move(PD^,FCC,4);
   SH:=PD;
   if SH^.fccType=ConvertFCCToDWORD(FCC_vids) then
    begin
     avi.vids.st:=sh^;
     inc(DWORD(PD),sh^.cb+8); //stay on "strf"
      move(PD^,FCC,4);
     inc(DWORD(PD),4); //stay on length "strf"
      move(PD^,leng,4);
     inc(DWORD(PD),4); //stay on "strf" data
     VFH:=PD;
     avi.vids.FMT.BMfmt:=VFH^.BMfmt;
     if leng>56 then
       avi.vids.FMT.DVFmt:=VFH^.DVFmt;
     inc(DWORD(PD),leng);//stay on LIST
     move(PD^,FCC,4);
    end;

    if SH^.fccType=ConvertFCCToDWORD("auds") then begin
     avi.auds[audstreams].st:=SH^;
      inc(DWORD(PD),sh^.cb+8); //stay on "strf"
      move(PD^,FCC,4);
     inc(DWORD(PD),4); //stay on length "strf"
      move(PD^,leng,4);
     inc(DWORD(PD),4); //stay on "strf" data
     WVH:=PD;
     avi.auds[audstreams].WAVFmt:=WVH^;
     inc(DWORD(PD),leng);
     inc(audstreams);
    end;
  Move(PD^,FCC,4);//Stay on JUNK or "strn"
  If (FCC=FCC_JUNK) or (FCC=FCC_strn) or (FCC=FCC_strd) or (FCC=FCC_indx) then
   begin
     inc(DWORD(PD),4);
      move(PD^,nuldd,4);
      If nuldd mod 2<>0 then inc(nuldd);
      inc(DWORD(PD),4+NULDD);
      move(PD^,FCC,4);
   end;
  End;
 avi.audstreams:=audstreams;
freemem(p);
end;


---
P.L.U.R. and WBR, NailMan aka 2:5020/3337.13


 
Noby   (2006-02-06 01:28) [15]

Огромное человеческое тебе СПАСИБО!!! выручил очень сильно:-)... буду пробовать



Страницы: 1 вся ветка

Текущий архив: 2006.07.16;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.035 c
1-1149146393
k_serg
2006-06-01 11:19
2006.07.16
ввод даннах в AutoCad


2-1151152802
b.o.n.d.007
2006-06-24 16:40
2006.07.16
Я не могу понять, почему Делфи не считает куски формулы?


15-1150268707
Megabyte
2006-06-14 11:05
2006.07.16
В полку инженеров прибыло! %)


15-1150355744
DillerXX
2006-06-15 11:15
2006.07.16
Программа для анимирования картинок.


2-1151576916
learner
2006-06-29 14:28
2006.07.16
Как отправить строку в нить ?