Опыт настройки HMS и Sony W5500 + несколько вопросов

Alex Commandor
Posts: 21
Joined: Sat Mar 13, 2010 2:22 pm

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alex Commandor »

Немножко доделал профиль "Фильмы - TsMuxer+AUDIO" - добавил запуск с любой позиции. Соответственно, заработала перемотка. НО! Как всегда, не обошлось без порядочной ложечки дегтя :( Оказалось, что тсМуксер при задании стартовой позиции файла начинает муксирование НЕ с этой позиции ( :shock: ), а как бы "перематывает" файл с самого начала, и только по достижении нужного времени начинает муксирование :?: Бред. В работе это выливается в то, что надо ставить значение "Прекращение транскодирования, если временный файл не используется" в 30 секунд (почему не больше - чуть дальше), дабы телику хватало времени дождаться начала потока :( Но и это еще не всё. При переходе на позицию, добраться до которой тсМуксеру надо более 30 секунд, добраться до нее не получается вообще - срабатывает, я так понимаю, таймаут телевизора (30 сек), ибо он пишет вместо "Воспроизведение невозможно" другую ошибку: "Не удается получить доступ к серверу" :cry:

Code: Select all

const
  csAC3TranscodingParams = '-i "%s" -acodec %s -ar 48000 -ab %d -map 0:%d -y -f %s "%s"';
  
function GetAudioBitrate(const aAudioCodec: string; aAudioBitrate: Integer): Integer;
begin
  if MatchText(aAudioCodec, ['MP2', 'MP3']) and (aAudioBitrate > 320000) then
    Result := 320000
  else
    Result := aAudioBitrate
end;
  
function GetAudioCodec(const aAudioCodec: string): string;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := 'ac3'
  else if SameText(aAudioCodec, 'AAC') then
    Result := 'libfaac'
  else if SameText(aAudioCodec, 'MP3') then
    Result := 'libmp3lame'
  else if SameText(aAudioCodec, 'MP2') then
    Result := 'mp2'
  else if SameText(aAudioCodec, 'WMA') then
    Result := 'wmav2'
  else
    Result := aAudioCodec
end;

function GetTsMuxerAudioCodec(const aAudioCodec: string): string;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := 'A_AC3'
  else if SameText(aAudioCodec, 'AAC') then
    Result := 'A_AAC'
  else if SameText(aAudioCodec, 'MP3') then
    Result := 'A_MP3'
  else if SameText(aAudioCodec, 'MP2') then
    Result := 'A_MP3'
  else
    Result := ''  
end;

function GetAudioFormat(const aAudioCodec: string): string;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := 'ac3'
  else if SameText(aAudioCodec, 'AAC') then
    Result := 'adts'
  else if SameText(aAudioCodec, 'MP3') then
    Result := 'mp3'
  else if SameText(aAudioCodec, 'MP2') then
    Result := 'mp3'
  else
    Result := aAudioCodec
end;

function SameAudioCodec(const aAudioCodec: string; aCodecID: Integer): Boolean;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := aCodecID = CODEC_ID_AC3
  else if SameText(aAudioCodec, 'AAC') then
    Result := aCodecID = CODEC_ID_AAC
  else if SameText(aAudioCodec, 'MP3') then
    Result := aCodecID = CODEC_ID_MP3
  else if SameText(aAudioCodec, 'MP2') then
    Result := aCodecID = CODEC_ID_MP3
  else if SameText(aAudioCodec, 'WMA') then
    Result := aCodecID = CODEC_ID_WMAV2
  else
    Result := False
end;

var
  i, iAudioStreamNo, iAudioCodecID, iVideoCodecID, 
  iAudioStreamID, iVideoStreamID: Integer;
  MetaFileLines: TStringList;
  sAudioInfo, sVideoInfo, sMetaFileName, 
  sInputVideoFileName, sInputAudioFileName, 
  sAC3TranscodingParams, sTimeShift,
  sFPS, sLANG: string;
  sAC3ReadPipeName, sAC3WritePipeName : Array[0..mpAudioStreams-1] of string; 
begin

    MetaFileLines := TStringList.Create;
    try
      sInputVideoFileName := mpFilePath;
      sInputAudioFileName := mpFilePath;

      if mpTimeStart <> '' then
        MetaFileLines.Add('MUXOPT --no-pcr-on-video-pid --vbr --vbv-len=500 --cut-start='
           + IntToStr(HmsTimeConvert(mpTimeStart)) + 's')
      else
        MetaFileLines.Add('MUXOPT --no-pcr-on-video-pid --vbr --vbv-len=500');

      iVideoCodecID := HmsGetStreamCodecID(stVideo, 0);
      if iVideoCodecID > 0 then begin   
        if (iVideoCodecID = CODEC_ID_H264) or SameText(mpVideoCodec, 'H264') then 
          sVideoInfo := 'V_MPEG4/ISO/AVC, "%s", level=4.1, insertSEI, contSPS'
        else if (iVideoCodecID = CODEC_ID_MPEG2VIDEO) or SameText(mpVideoCodec, 'MPEG2VIDEO') then
          sVideoInfo := 'V_MPEG-2, "%s"'
        else if (iVideoCodecID = CODEC_ID_VC1) or SameText(mpVideoCodec, 'VC1') then
          sVideoInfo := 'V_MS/VFW/WVC1, "%s"'
        else   
          sVideoInfo := '';
         end;          

        if sVideoInfo <> '' then begin
          if SameText(ExtractFileExt(mpFilePath), '.mkv') then begin
            iVideoStreamID := HmsGetStreamIndex(stVideo, 0) + 1;
          end else begin  
            iVideoStreamID := HmsGetStreamID(stVideo, 0);  
            if SameText(ExtractFileExt(mpFilePath), '.vob') then begin
              iVideoStreamID := iVideoStreamID and 255;
            end;
          end;

          sFPS := 'fps=%2.3f';
          sFPS := Format(sFPS, [mpFrameRate]);
          sFPS := ReplaceStr(sFPS, ',', '.');
          sVideoInfo := sVideoInfo + ', track=%d, %s, lang=';
          sLANG := HmsGetStreamLanguage(stVideo, iVideoStreamID);
          if SameText(sLANG, '') then sLANG := 'eng';
          sVideoInfo := sVideoInfo + sLANG;
          MetaFileLines.Add(Format(sVideoInfo, [sInputVideoFileName, iVideoStreamID, sFPS]));
       end;

      for i := 0 to mpAudioStreams-1 do begin
        iAudioStreamNo := i;
        sInputAudioFileName := mpFilePath;
      iAudioCodecID := HmsGetStreamCodecID(stAudio, iAudioStreamNo);
        if iAudioCodecID = CODEC_ID_AC3 then  
          sAudioInfo := 'A_AC3'
        else if iAudioCodecID = CODEC_ID_DTS then
          sAudioInfo := 'A_DTS'
        else if iAudioCodecID = CODEC_ID_MP3 then
          sAudioInfo := 'A_MP3'
        else if iAudioCodecID = CODEC_ID_MP2 then
          sAudioInfo := 'A_MP3'
        else if iAudioCodecID = CODEC_ID_AAC then
          sAudioInfo := 'A_AAC'
        else
          sAudioInfo := '';
        if sAudioInfo <> '' then begin
          if SameText(ExtractFileExt(mpFilePath), '.mkv') then begin
            iAudioStreamID := HmsGetStreamIndex(stAudio, iAudioStreamNo) + 1;
          end else begin  
            iAudioStreamID := HmsGetStreamID(stAudio, iAudioStreamNo);
            if SameText(ExtractFileExt(mpFilePath), '.vob') then begin
              iAudioStreamID := iAudioStreamID and 255;
            end
          end;    
          if not SameAudioCodec(cfgTranscodingAudioCodec, iAudioCodecID) then begin
            if HmsCreateDualPipe(sAC3ReadPipeName[i], sAC3WritePipeName[i], 10000000) then begin
              sAC3TranscodingParams := Format(csAC3TranscodingParams, 
                  [mpFilePath, GetAudioCodec(cfgTranscodingAudioCodec ), 
                   GetAudioBitrate(cfgTranscodingAudioCodec, cfgTranscodingAudioBitrate),  
                   HmsGetStreamIndex(stAudio, iAudioStreamNo), 
                   GetAudioFormat(cfgTranscodingAudioCodec), sAC3WritePipeName[i]]);
              if HmsTranscodingExecute('HMSMPEG', sAC3TranscodingParams, False) then begin     
                sInputAudioFileName := sAC3ReadPipeName[i];
                sAudioInfo := GetTsMuxerAudioCodec(cfgTranscodingAudioCodec);
                iAudioStreamID := 1;
              end  
            end   
          end;
          sTimeShift := HmsGetVideoSettings(vstAudioDelay);
          if sTimeShift <> '' then
             sTimeShift := Format(', timeshift=%ss', [sTimeShift]);
          sAudioInfo := sAudioInfo + ', "%s", ' + 'track=%d' + sTimeShift;
          sAudioInfo := sAudioInfo + ', lang=';
          sLANG := HmsGetStreamLanguage(stAudio, iAudioStreamNo);
          if SameText(sLANG, '') then sLANG := 'eng';
          sAudioInfo := sAudioInfo + sLANG;
          MetaFileLines.Add(Format(sAudioInfo, [sInputAudioFileName, iAudioStreamID]));
        end;
        end;
          sMetaFileName := ChangeFileExt(OutputFileName, '.meta');
          MetaFileLines.SaveToFile(sMetaFileName);
          OutputFileName := ChangeFileExt(OutputFileName, '.m2ts');
          TranscodingResult := HmsTranscodingExecute('TSMUXER', '"' + sMetaFileName + '" "' + OutputFileName + '"', True);
    finally
      MetaFileLines.Free
  end
// end  
end.
Короче, одна засада. Я так понимаю, что просто тсМуксером сделать полноценный профиль с поддержкой всех дорожек НЕ получится. Я тут уже пробовал перейти на транскодирование через VLC, но пока что не совсем разобрался с его параметрами. Да и тут сразу же полезли странности: тестовое транскодирование проходит нормально, полученный файл читается на компе, НО на телик транскодируется битыми пикселями и с одной аудио :( Пробовал кинуть полученный файл просто в папку с фильмами, и получил ту же фигню. Пока что не хватает времени разобраться в свойствах полученного файла, чтобы понять, что в нем не так.
Вот что о нем говорит МедиаИнфо:

Code: Select all

 Название свойства/значение |  |  
 - | Общее |  
  |  | Идентификатор: 30ED 
  |  | Полное имя: J:\VIDEO\Юмор\Test_4869a1a679694384a9862b3941e15d46.m2ts 
  |  | Формат: MPEG-TS 
  |  | Размер файла: 200 МиБ 
  |  | Продолжительность: 2 м. 31 с. 
  |  | Общий поток: 11,1 Мбит/сек 
 - | Видео |  
  |  | Идентификатор: 74 (0x4A) 
  |  | Идентификатор меню: 1 (0x1) 
  |  | Формат: MPEG Video 
  |  | Версия формата: Version 2 
  |  | Профайл формата: Main@High 1440 
  |  | Параметры BVOP формата: Нет 
  |  | Параметры матрицы формата: По умолчанию 
  |  | Format_Settings_GOP: M=1, N=12 
  |  | Идентификатор кодека: 2 
  |  | Продолжительность: 2 м. 31 с. 
  |  | Вид битрейта: Постоянный 
  |  | Битрейт: 8000 Кбит/сек 
  |  | Ширина: 1280 пикс. 
  |  | Высота: 720 пикс. 
  |  | Соотношение кадра: 16:9 
  |  | Частота кадров: 24,000 кадр/сек 
  |  | ColorSpace: YUV 
  |  | ChromaSubsampling: 4:2:0 
  |  | BitDepth/String: 8 бит 
  |  | Тип развёртки: Прогрессивная 
  |  | Бит/(Пиксели*Кадры): 0.362 
  |  | Размер потока: 141 МиБ (71%) 
  |  | Язык: English 
 - | Аудио #1 |  
  |  | Идентификатор: 68 (0x44) 
  |  | Идентификатор меню: 1 (0x1) 
  |  | Формат: AC-3 
  |  | Формат/Информация: Audio Coding 3 
  |  | Format_Settings_ModeExtension: CM (complete main) 
  |  | Идентификатор кодека: 129 
  |  | Продолжительность: 2 м. 31 с. 
  |  | Вид битрейта: Постоянный 
  |  | Битрейт: 448 Кбит/сек 
  |  | Канал(ы): 6 канала(ов) 
  |  | Расположение каналов: Front: L C R, Side: L R, LFE 
  |  | Частота: 44,1 КГц 
  |  | BitDepth/String: 16 бит 
  |  | Размер потока: 8,11 МиБ (4%) 
  |  | Язык: Russian
 - | Аудио #2 |  
  |  | Идентификатор: 69 (0x45) 
  |  | Идентификатор меню: 1 (0x1) 
  |  | Формат: AC-3 
  |  | Формат/Информация: Audio Coding 3 
  |  | Format_Settings_ModeExtension: CM (complete main) 
  |  | Идентификатор кодека: 129 
  |  | Продолжительность: 2 м. 31 с. 
  |  | Вид битрейта: Постоянный 
  |  | Битрейт: 448 Кбит/сек 
  |  | Канал(ы): 6 канала(ов) 
  |  | Расположение каналов: Front: L C R, Side: L R, LFE 
  |  | Частота: 44,1 КГц 
  |  | BitDepth/String: 16 бит 
  |  | Размер потока: 8,11 МиБ (4%) 
  |  | Язык: Russian
Посему у меня возникла самая кардинальная идея за все время эксплуатации моего W5500 :D Хочу обратиться к автору этой без преувеличения замечательнейшей программы с просьбой: помогите нам в создании профиля, который генерит НОРМАЛЬНЫЙ m2ts-файл (либо ts-поток) со всеми звуковыми дорожками и с разрешениями либо 1280х720, либо 1920х1080. В идеале, думаю, было бы классно, если бы БЕЗ транскодинга в поток передавались только форматы видео AVC(H264) и MPEG1/2, а аудио - AC3 и MP3. Но мне так кажется, что можно даже ВСЁ транскодировать на лету в MPEG2 и AC3 (6 каналов), лишь бы телик всё понимал и нормально перематывал.
Вот ;)

З.Ы. Размеры нашей благодарности будут безграничны в пределах разумного :)
HMS 1.21.2 + Sony KDL32W5500, Win7 x64 Ultimate, Core2Duo E8500 3.16GHz, 8GB RAM, ATI Radeon 4870HD 512MB + NVIDIA GeForce GT 440 1GB (hybrid PhysX)
Alexander Great
Posts: 99
Joined: Wed Mar 10, 2010 9:24 am

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alexander Great »

Посему у меня возникла самая кардинальная идея за все время эксплуатации моего W5500 Хочу обратиться к автору этой без преувеличения замечательнейшей программы с просьбой: помогите нам в создании профиля, который генерит НОРМАЛЬНЫЙ m2ts-файл (либо ts-поток) со всеми звуковыми дорожками и с разрешениями либо 1280х720, либо 1920х1080.
Этого можно добиться, всего лишь взведя галку "Формат файл, контейнер - MPEG (TS)" и используя ваш профиль "Фильмы - Основной + Audio". Принципиальной разницы с настройками по умолчанию не будет к сожалению.

А за новый профиль, спасибо, протестирую как доберусь домой. (Через неделю). ;)
Alex Commandor
Posts: 21
Joined: Sat Mar 13, 2010 2:22 pm

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alex Commandor »

Alexander Great wrote:Этого можно добиться, всего лишь взведя галку "Формат файл, контейнер - MPEG (TS)" и используя ваш профиль "Фильмы - Основной + Audio". Принципиальной разницы с настройками по умолчанию не будет к сожалению.
К сожалению, как раз принципиальная разница и будет: если включить галку "Формат файл, контейнер - MPEG (TS)", то телик вообще видит только ОДИН звук, да и тот не проигрывается, а вместо видео - набор разноцветных квадратиков, в которых при большой фантазии можно угадать картинку ;) Я уже много каких галок перепробовал в настройках - не помогает ничего, кроме муксирования тсМуксером. Но из-за его глюка с ненулевым началом файла этот вариант остается тоже не очень удобоваримым :( Такое впечатление, что, кроме тсМуксера, ни одна программа не создает КОРРЕКТНЫЙ транспортный поток. Потому я и обратился к автору - если даже принудительное включение контейнера MPEG (TS) (которое вроде по логике должно помочь) не срабатывает, то только автор может разобраться, в чем там дело.
HMS 1.21.2 + Sony KDL32W5500, Win7 x64 Ultimate, Core2Duo E8500 3.16GHz, 8GB RAM, ATI Radeon 4870HD 512MB + NVIDIA GeForce GT 440 1GB (hybrid PhysX)
Alexander Great
Posts: 99
Joined: Wed Mar 10, 2010 9:24 am

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alexander Great »

Хм. Странно... У меня с какими-то настройками, телек нормально показывал, точно помню, с включенным контейнером MPEGTS вместо DVD. Но не буду спорить, помню что и глючило когда-то капитально.

В общем я понял, что вы хотите: еще одну галочку в настройках контейнера, типа "Контейнер m2ts". Тогда я присоединяюсь к просьбе. Точно знаю, что автор читает форум, но крайне редко отвечает. ;)

Кстати, тсмуксер, тот что графический, это просто фронтэнд для тсмуксера для командной строки. Дело видимо в том, что мы хотим добиться не предобработки, а обработки фактически в реальном времени. Не могу понять, что происходит в этом случае, при вставлении более одной дорожки.
Alex Commandor
Posts: 21
Joined: Sat Mar 13, 2010 2:22 pm

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alex Commandor »

Alexander Great wrote:Дело видимо в том, что мы хотим добиться не предобработки, а обработки фактически в реальном времени. Не могу понять, что происходит в этом случае, при вставлении более одной дорожки.
Тут получается без разницы, в реальном времени или предобработка, одна дорожка или много :( . Я уже писАл, что тсМуксер при указании позиции старта не делает муксирование сразу с указанного времени, а типа "перематывает" файл - пАрсит его - до нужной позиции (всё это время выходной файл имеет нулевую длину!), и только с нужной временнОй позиции начинает муксирование в файл. Это всё происходит даже в случае абсолютно корректных аудио-видео-дорожек, которым не нужно транскодирование :(
У меня тут есть уже одна идея, на которую никак не найду времени :) Я думаю, что надо совсем уйти от обработки тсМуксером исходного файла, а вместо этого подавать ему pipe от транскодирования через HMSMPEG. Т.е. тот мой профиль, который просто "Фильмы - Основной + Audio", можно же запускать с любой позиции файла, и тогда тсМуксер будет получать псевдофайл (поток) якобы с самого начала. Т.е. задержки при перемотке вообще не должно бы быть. Но это в теории. Как оно будет на практике, проверю дома, потому как на работе нечем :(
HMS 1.21.2 + Sony KDL32W5500, Win7 x64 Ultimate, Core2Duo E8500 3.16GHz, 8GB RAM, ATI Radeon 4870HD 512MB + NVIDIA GeForce GT 440 1GB (hybrid PhysX)
Alexander Great
Posts: 99
Joined: Wed Mar 10, 2010 9:24 am

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alexander Great »

2 Alex Commandor

Здравствуйте. Есть какие-то успехи?

Я не могу понять почему перемотка с ТсМуксером, спокойно работает при одной дорожке, и не работает как положенно с вашим профилем, на сколько угодно дорожек? Вы разобрались? Проблема с самим Муксером?
Alex Commandor
Posts: 21
Joined: Sat Mar 13, 2010 2:22 pm

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alex Commandor »

М-дя... Здравствуйте :)
Успехи - это как мёд в мультике про Винни-Пуха: если он есть, так его сразу уже и нету :lol:
Если коротко, то меня пока что жутко сдерживает отсутствие тихого и спокойного свободного времени. Весь день на работе, вечером практически некогда ковыряться, а на выходных - когда как :(
Пока что я смог выяснить только несколько нюансов.

1) Сделать так, как я хотел (и писал об этом чуть раньше), не складывается :( Я хотел результат транскодирования HMSMPEG-ом муксировать на лету тсМуксером, - получилось ноль целых хрен десятых :evil: Привожу скрипт:

Code: Select all

var
  i, iAudioStreamNo, iAudioCodecID, iVideoCodecID, 
  iAudioStreamID, iVideoStreamID: Integer;
  MetaFileLines: TStringList;
  sAudioInfo, sVideoInfo, sMetaFileName, 
  sInputVideoFileName, sInputAudioFileName, 
  sAC3TranscodingParams, sTimeShift, sHMSTranscodingParams,
  sFPS, sLANG, sReadPipe, sWritePipe: string;
  td1, td2: tDateTime;

begin

    MetaFileLines := TStringList.Create;
    sHMSTranscodingParams :=HmsTranscodingProfileParams('Фильмы (основной)+AUDIO');
    sHMSTranscodingParams := ReplaceStr(sHMSTranscodingParams, '-acodec copy', '-acodec ac3 -ab 448000 -ar 48000 -ac 6');

try

     if HmsCreateDualPipe(sReadPipe, sWritePipe) then begin
        sHMSTranscodingParams := ReplaceStr(sHMSTranscodingParams, '<OUTPUT FILE>', sWritePipe);
        if HmsTranscodingExecute('HMSMPEG', sHMSTranscodingParams, False) then begin

//          HmsDumpPipe(sReadPipe, OutputFileName + '__.mpg',True) ;
//          InputFileName := OutputFileName + '__.mpg';
//          sInputVideoFileName := OutputFileName + '__.mpg';
//          sInputAudioFileName := OutputFileName + '__.mpg';
//          mpFilePath := OutputFileName + '__.mpg';

          InputFileName := sReadPipe;
          sInputVideoFileName := sReadPipe;
          sInputAudioFileName := sReadPipe;
          mpFilePath := sReadPipe;

// - этот цикл - попытка задержать запуск тсМуксера до начала транскодирования ффмпегом
//----------------
          td1 := Time;
          td2 := IncTime(td1,0,0,mpAudioStreams*3,0);
          repeat
          until Time>=td2;
//----------------
          
        end
     else
        exit
     end;

//      if mpTimeStart <> '' then
//        MetaFileLines.Add('MUXOPT --no-pcr-on-video-pid --new-audio-pes --vbr --vbv-len=500 --cut-start='
//           + IntToStr(HmsTimeConvert(mpTimeStart)) + 's')
//      else
        MetaFileLines.Add('MUXOPT --no-pcr-on-video-pid --vbr --vbv-len=500');

          sVideoInfo := 'V_MPEG-2, "%s"';
          iVideoStreamID := HmsGetStreamID(stVideo, 0)+223;
//          sFPS := 'fps=%2.3f';
//          sFPS := Format(sFPS, [mpFrameRate]);
//          sFPS := ReplaceStr(sFPS, ',', '.');
          sVideoInfo := sVideoInfo + ', track=%d, lang=';
          sLANG := HmsGetStreamLanguage(stVideo, iVideoStreamID);
          if SameText(sLANG, '') then sLANG := 'eng';
          sVideoInfo := sVideoInfo + sLANG;
          MetaFileLines.Add(Format(sVideoInfo, [sInputVideoFileName, iVideoStreamID]));//, sFPS]));
      for i := 0 to mpAudioStreams-1 do begin
        iAudioStreamNo := i;
        sInputAudioFileName := mpFilePath;
        sAudioInfo := 'A_AC3';
        iAudioStreamID := HmsGetStreamID(stAudio, iAudioStreamNo)+126;
        sTimeShift := HmsGetVideoSettings(vstAudioDelay);
        if sTimeShift <> '' then
           sTimeShift := Format(', timeshift=%ss', [sTimeShift]);
        sAudioInfo := sAudioInfo + ', "%s", ' + 'track=%d' + sTimeShift;
        sAudioInfo := sAudioInfo + ', lang=';
        sLANG := HmsGetStreamLanguage(stAudio, iAudioStreamNo);
        if SameText(sLANG, '') then sLANG := 'eng';
        sAudioInfo := sAudioInfo + sLANG;
        MetaFileLines.Add(Format(sAudioInfo, [sInputAudioFileName, iAudioStreamID]));
        end;
          sMetaFileName := ChangeFileExt(OutputFileName, '.meta');
          MetaFileLines.SaveToFile(sMetaFileName);
          OutputFileName := ChangeFileExt(OutputFileName, '.m2ts');
          TranscodingResult := HmsTranscodingExecute('TSMUXER', '"' + sMetaFileName + '" "' + OutputFileName + '"', True);
    finally
      MetaFileLines.Free
  end
end.
Он в черновом виде (т.е. не вычищен до конца). В нем реализовано то, как, по моемУ мнению, должно бы это всё выглядеть: исходный видеофайл запускается на транскодирование HMSMPEG-ом (притом ВСЕ аудио и одна видео-дорожки), результат вместо файла перенаправляется в пайп, из которого тсМуксер читает данные и муксит их в выходной файл. Только обломал меня тсМуксер с таким подходом :? При запуске профиля тсМуксер практически сразу же отключается от пайпа - такое впечатление, что он считывает столько данных, сколько успевает передать ффмпег, и на этом всё заканчивается. Это подтверждается тем, что при наличии многих аудиодорожек тсМуксер вообще ничего не успевает смуксить. Я даже из-за этого попытался там вставить цикл ожидания начала запуска тсМуксера в зависимости от количества звуковых дорог, - всё равно бестолку :cry: Пробовал вместо пайпа генерить файл (в профиле там есть закомментированные строки), и уже этот файл давать тсМуксеру, - такая же фигня. Т.е. сколько в файл успело нагенериться, столько тсМуксер и намуксил :(
Думаю, что надо как-то избежать вызова транскодинга другим профилем, как я тут попытался сделать, а сдеалть всё в одном профиле, но как это сделать, я пока не знаю.

2) Другая загадка - доработанный профиль "Фильмы - TsMuxer+AUDIO" (у меня он называется "Фильмы - TsMuxer+AUDIO_1"). Всё то же, что и в последнем РАБОЧЕМ профиле, только еще добавлено транскодирование видео, если размер НЕ 1280х720 или НЕ 1920х1080.

Code: Select all

const
  csAC3TranscodingParams = ' -i "%s" -vn -acodec %s -ar 48000 -ab %d -map 0:%d -y -f %s "%s"';
  cs720TranscodingParams = ' -probesize 7000000 -analyzeduration 5000000 -i "%s" -f dvd -pix_fmt yuv420p -vcodec mpeg2video -b 8000k -re -copyts -aspect 16:9 -map 0:0 -an -threads 2 -s hd720 -y -sws_flags lanczos "%s"';
  cs1080TranscodingParams = ' -probesize 7000000 -analyzeduration 5000000 -i "%s" -f dvd -pix_fmt yuv420p -vcodec mpeg2video -b 8000k -re -copyts -aspect 16:9 -map 0:0 -an -threads 2 -s hd1080 -y -sws_flags lanczos "%s"';
  
function GetAudioBitrate(const aAudioCodec: string; aAudioBitrate: Integer): Integer;
begin
  if MatchText(aAudioCodec, ['MP2', 'MP3']) and (aAudioBitrate > 320000) then
    Result := 320000
  else
    Result := aAudioBitrate
end;
  
function GetAudioCodec(const aAudioCodec: string): string;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := 'ac3'
  else if SameText(aAudioCodec, 'AAC') then
    Result := 'libfaac'
  else if SameText(aAudioCodec, 'MP3') then
    Result := 'libmp3lame'
  else if SameText(aAudioCodec, 'MP2') then
    Result := 'mp2'
  else if SameText(aAudioCodec, 'WMA') then
    Result := 'wmav2'
  else
    Result := aAudioCodec
end;

function GetTsMuxerAudioCodec(const aAudioCodec: string): string;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := 'A_AC3'
  else if SameText(aAudioCodec, 'AAC') then
    Result := 'A_AAC'
  else if SameText(aAudioCodec, 'MP3') then
    Result := 'A_MP3'
  else if SameText(aAudioCodec, 'MP2') then
    Result := 'A_MP3'
  else
    Result := ''  
end;

function GetAudioFormat(const aAudioCodec: string): string;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := 'ac3'
  else if SameText(aAudioCodec, 'AAC') then
    Result := 'adts'
  else if SameText(aAudioCodec, 'MP3') then
    Result := 'mp3'
  else if SameText(aAudioCodec, 'MP2') then
    Result := 'mp2'
  else
    Result := aAudioCodec
end;

function SameAudioCodec(const aAudioCodec: string; aCodecID: Integer): Boolean;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := aCodecID = CODEC_ID_AC3
  else if SameText(aAudioCodec, 'AAC') then
    Result := aCodecID = CODEC_ID_AAC
  else if SameText(aAudioCodec, 'MP3') then
    Result := aCodecID = CODEC_ID_MP3
  else if SameText(aAudioCodec, 'MP2') then
    Result := aCodecID = CODEC_ID_MP2
  else if SameText(aAudioCodec, 'WMA') then
    Result := aCodecID = CODEC_ID_WMAV2
  else
    Result := False
end;

var
  i, iAudioStreamNo, iAudioCodecID, iVideoCodecID, 
  iAudioStreamID, iVideoStreamID, iPadTop: Integer;
  MetaFileLines: TStringList;
  sAudioInfo, sVideoInfo, sMetaFileName, 
  sInputVideoFileName, sInputAudioFileName, 
  sAC3TranscodingParams, sTimeShift, sAVCReadPipeName, sAVCWritePipeName,
  sFPS, sLANG, sAVCTranscodingParams: string;
  sAC3ReadPipeName, sAC3WritePipeName : Array[0..mpAudioStreams-1] of string; 
begin

 //sAVCTranscodingParams := HmsTranscodingInputParams + HmsTranscodingVideoCodecParams(1920, 1080, 8000000, True); 

    MetaFileLines := TStringList.Create;
    try
      sInputVideoFileName := mpFilePath;
      sInputAudioFileName := mpFilePath;

      if mpTimeStart <> '' then
        MetaFileLines.Add('MUXOPT --no-pcr-on-video-pid --new-audio-pes --vbr --vbv-len=500 --cut-start='
           + IntToStr(HmsTimeConvert(mpTimeStart)) + 's')
      else
        MetaFileLines.Add('MUXOPT --no-pcr-on-video-pid --new-audio-pes --vbr --vbv-len=500');

      iVideoCodecID := HmsGetStreamCodecID(stVideo, 0);
      if iVideoCodecID > 0 then begin   
        if (iVideoCodecID = CODEC_ID_H264) or SameText(mpVideoCodec, 'H264') then 
          sVideoInfo := 'V_MPEG4/ISO/AVC, "%s", level=4.1, insertSEI, contSPS'
        else if (iVideoCodecID = CODEC_ID_MPEG2VIDEO) or SameText(mpVideoCodec, 'MPEG2VIDEO') then
          sVideoInfo := 'V_MPEG-2, "%s"'
        else if (iVideoCodecID = CODEC_ID_VC1) or SameText(mpVideoCodec, 'VC1') then
          sVideoInfo := 'V_MS/VFW/WVC1, "%s"'
        else   
          sVideoInfo := '';
         end;          

        if sVideoInfo <> '' then begin
          if SameText(ExtractFileExt(mpFilePath), '.mkv') then begin
            iVideoStreamID := HmsGetStreamIndex(stVideo, 0) + 1;
          end else begin  
            iVideoStreamID := HmsGetStreamID(stVideo, 0);  
            if SameText(ExtractFileExt(mpFilePath), '.vob') then begin
              iVideoStreamID := iVideoStreamID and 255;
            end;
          end;

          sLANG := HmsGetStreamLanguage(stVideo, iVideoStreamID);
          if SameText(sLANG, '') then sLANG := 'eng';
          sFPS := 'fps=%2.3f';
          sFPS := Format(sFPS, [mpFrameRate]);
          sFPS := ReplaceStr(sFPS, ',', '.');

          if not (((mpWidth=1920) and (mpHeight=1080)) or ((mpWidth=1280) and (mpHeight=720)))then begin
            if mpWidth<=1280 then 
               sAVCTranscodingParams := cs720TranscodingParams
            else
               sAVCTranscodingParams := cs1080TranscodingParams;
               
            if HmsCreateDualPipe(sAVCReadPipeName, sAVCWritePipeName) then begin
//              sAVCTranscodingParams := Format(sAVCTranscodingParams,
//                  [sInputVideoFileName, ReplaceStr(sFPS, 'fps=', ''), sAVCWritePipeName]);
              sAVCTranscodingParams := Format(sAVCTranscodingParams,
                  [sInputVideoFileName, sAVCWritePipeName]);
              if HmsTranscodingExecute('HMSMPEG', sAVCTranscodingParams, False) then begin
//                HmsDumpPipe(sAVCReadPipeName, 'J:\TEMP\HmsTemp\sdsdsd.mpg', True);
                sInputVideoFileName := sAVCReadPipeName;
                iVideoStreamID := 1;
                sVideoInfo := ReplaceStr(sVideoInfo, 'V_MPEG4/ISO/AVC, "%s", level=4.1, insertSEI, contSPS', 'V_MPEG-2, "%s"');
                sVideoInfo := ReplaceStr(sVideoInfo, 'V_MS/VFW/WVC1, "%s"', 'V_MPEG-2, "%s"');
                sFPS := 'fps=25';
              end  
            end   
          end;
          
          sVideoInfo := sVideoInfo + ', track=%d, %s, lang=';
          sVideoInfo := sVideoInfo + sLANG;
          MetaFileLines.Add(Format(sVideoInfo, [sInputVideoFileName, iVideoStreamID, sFPS]));
       end;

      for i := 0 to mpAudioStreams-1 do begin
        iAudioStreamNo := i;
        sInputAudioFileName := mpFilePath;
      sTimeShift := HmsGetVideoSettings(vstAudioDelay);
      if sTimeShift <> '' then
        sTimeShift := Format(', timeshift=%ss', [sTimeShift]);

      iAudioCodecID := HmsGetStreamCodecID(stAudio, iAudioStreamNo);
        if iAudioCodecID = CODEC_ID_AC3 then  
          sAudioInfo := 'A_AC3'
        else if iAudioCodecID = CODEC_ID_DTS then
          sAudioInfo := 'A_DTS'
        else if iAudioCodecID = CODEC_ID_MP3 then
          sAudioInfo := 'A_MP3'
        else if iAudioCodecID = CODEC_ID_MP2 then
          sAudioInfo := 'A_MP3'
        else if iAudioCodecID = CODEC_ID_AAC then
          sAudioInfo := 'A_AAC'
        else
          sAudioInfo := '';
        if sAudioInfo <> '' then begin
          if SameText(ExtractFileExt(mpFilePath), '.mkv') then begin
            iAudioStreamID := HmsGetStreamIndex(stAudio, iAudioStreamNo) + 1;
          end else begin  
            iAudioStreamID := HmsGetStreamID(stAudio, iAudioStreamNo);
            if SameText(ExtractFileExt(mpFilePath), '.vob') then begin
              iAudioStreamID := iAudioStreamID and 255;
            end
          end;    
          if not SameAudioCodec(cfgTranscodingAudioCodec, iAudioCodecID) then begin
            if HmsCreateDualPipe(sAC3ReadPipeName[i], sAC3WritePipeName[i]) then begin
              sAC3TranscodingParams := Format(csAC3TranscodingParams, 
                  [mpFilePath, GetAudioCodec(cfgTranscodingAudioCodec ), 
                   GetAudioBitrate(cfgTranscodingAudioCodec, cfgTranscodingAudioBitrate),  
                   HmsGetStreamIndex(stAudio, iAudioStreamNo), 
                   GetAudioFormat(cfgTranscodingAudioCodec), sAC3WritePipeName[i]]);
              if HmsTranscodingExecute('HMSMPEG', sAC3TranscodingParams, False) then begin     
                sInputAudioFileName := sAC3ReadPipeName[i];
                sAudioInfo := GetTsMuxerAudioCodec(cfgTranscodingAudioCodec);
                iAudioStreamID := 1;
              end  
            end   
          end;
          sAudioInfo := sAudioInfo + ', "%s", ' + 'track=%d' + sTimeShift;
          sAudioInfo := sAudioInfo + ', lang=';
          sLANG := HmsGetStreamLanguage(stAudio, iAudioStreamNo);
          if SameText(sLANG, '') then sLANG := 'eng';
          sAudioInfo := sAudioInfo + sLANG;
          MetaFileLines.Add(Format(sAudioInfo, [sInputAudioFileName, iAudioStreamID]));
        end;
        end;
          sMetaFileName := ChangeFileExt(OutputFileName, '.meta');
          MetaFileLines.SaveToFile(sMetaFileName);
          OutputFileName := ChangeFileExt(OutputFileName, '.m2ts');
          TranscodingResult := HmsTranscodingExecute('TSMUXER', '"' + sMetaFileName + '" "' + OutputFileName + '"', True);
    finally
      MetaFileLines.Free
  end  
end.
Он тоже не вычищен до конца, потому как толком не заработал. Причина - полученное видео почему-то рассыпается квадратиками :evil: Я просто задолбался искать причину этого, и так пока и не нашел :evil: Если ловить пайп и записывать его в файл, полученное видео на-ура воспроизводится на компьютере. Если же муксить, то звуковые дороги есть ВСЕ, а вот видео, как я уже сказал, всё "рассыпчастое" :(
Я, правда, пока не нашел времени проверить, воспроизводится ли захваченный на диск пайп (и записанный на флешку) самим телевизором, но думаю, что тоже не воспроизведется. Скорее всего, проблема в сгенерированном ффмпегом потоке, но я пока что не нашел причину этого глюка.
Да и в любом случае, никуда не исчезает глюк тсМуксера с перемоткой "на дальние расстояния". Так что планы я пока что перенаправляю в сторону ухода от тсМуксера и тестирования каких-то других кодировщиков (напр., VLC). Но это уже когда появится время.
З.Ы. Да, может, и автор таки откликнется на просьбу ;)
HMS 1.21.2 + Sony KDL32W5500, Win7 x64 Ultimate, Core2Duo E8500 3.16GHz, 8GB RAM, ATI Radeon 4870HD 512MB + NVIDIA GeForce GT 440 1GB (hybrid PhysX)
Alexander Great
Posts: 99
Joined: Wed Mar 10, 2010 9:24 am

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alexander Great »

Я вот думаю, а нельзя ли как-то использовать hmsmpeg (ffmpeg) для этих же целей? Имею в виду следующее. В случае стандартных разрешений, вызывать hmsmpeg с ключами -vcodec copy -acodec copy, но чтобы он создавал не mpeg контейнер а m2ts. Ведь в итоге будет тоже самое, что делает тсмуксер.
Alex Commandor
Posts: 21
Joined: Sat Mar 13, 2010 2:22 pm

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alex Commandor »

Alexander Great wrote:Я вот думаю, а нельзя ли как-то использовать hmsmpeg (ffmpeg) для этих же целей? Имею в виду следующее. В случае стандартных разрешений, вызывать hmsmpeg с ключами -vcodec copy -acodec copy, но чтобы он создавал не mpeg контейнер а m2ts. Ведь в итоге будет тоже самое, что делает тсмуксер.
Не будет то же самое :? Я пробовал менять "-f dvd" на "-f mpegts" + менять расширение файла на "m2ts" + пробовал ставить для всего профиля миме-тип "m2ts" (не помню сейчас полную строку DLNA-типа) + пробовал это всё в разных комбинациях - результата ноль :( В лучшем случае - нормальное видео + те же ДВА звука...
Я потому и написал в предыдущем посте, что буду смотреть в сторону других кодировщиков, потому как закрадывается такая мыслЯ, что ФФМПЕГ генерит некорректный транспортный поток (или даже более глобально - мпег2-поток, который не соответствует строго требованиям MPEG2 Transport Stream).
Справедливости ради хочу сказать, что я совсем не исключаю, что я не до конца разобрался с параметрами ФФМПЕГ-а, хотя по всем найденным мною мануалам, примерам, описаниям, хелпам и т.п. вроде всё настроено правильно. Тем не менее, имеют место глюки. :( Я до сих пор не понимаю, почему при генерации МПЕГ2-потока, совместимого с форматом ДВД (-f dvd) получается нормальный mpg-файл, в котором есть ВСЕ аудио-дорожки, а телик понимает из них только две :? И почему изменение контейнера (-f mpegts) генерит файл, который телик воспроизводит битыми квадратиками? Короче, пока что засада.
HMS 1.21.2 + Sony KDL32W5500, Win7 x64 Ultimate, Core2Duo E8500 3.16GHz, 8GB RAM, ATI Radeon 4870HD 512MB + NVIDIA GeForce GT 440 1GB (hybrid PhysX)
Alexander Great
Posts: 99
Joined: Wed Mar 10, 2010 9:24 am

Re: Опыт настройки HMS и Sony W5500 + несколько вопросов

Post by Alexander Great »

-f mpegts - даст контейнер ts а не m2ts, который требуется для воспроизведения h264. Хоть бы добиться m2ts + h264 + 2 аудио дорожки... :oops:

http://en.wikipedia.org/wiki/MPEG_transport_stream
http://en.wikipedia.org/wiki/.m2ts

М-да... Гуглю-гуглю... Не могу найти как сделать m2ts с помощью ffmpeg. Думал, может прикрутить mencoder. Тоже не пойму как им сделать m2ts.

Судя по всему, сделать m2ts можно только tsmuxer-ом или vlc.

Но еще предлагают такой вариант ffmpeg -r 23.976 -f h264 -i input.h264 -f ac3 -i input.ac3 -vcodec copy -acodec copy -f vob output.vob :shock: Говорят что работает на PS3. А наши с вами телеки, это практически тоже что PS3, только еще чуть тупее. ;)
Post Reply