OSDN Git Service

Provide more feedback as to the types of the streams in an MPEG Transport stream
[handbrake-jp/handbrake-jp-git.git] / libhb / stream.c
index e376c69..478aef1 100755 (executable)
@@ -57,6 +57,7 @@ struct hb_stream_s
     uint8_t ts_number_audio_pids;
 
     uint8_t ts_streamid[kMaxNumberDecodeStreams];
+    uint8_t ts_video_stream_type[kMaxNumberDecodeStreams];
     uint8_t ts_audio_stream_type[kMaxNumberDecodeStreams];
 
     char    *path;
@@ -340,7 +341,7 @@ void hb_stream_close( hb_stream_t ** _d )
     if ( stream->frames )
     {
         hb_log( "stream: %d good frames, %d errors (%.0f%%)", stream->frames,
-                stream->errors, (double)stream->errors * 100. / 
+                stream->errors, (double)stream->errors * 100. /
                 (double)stream->frames );
     }
     /*
@@ -444,7 +445,7 @@ hb_title_t * hb_stream_title_scan(hb_stream_t *stream)
         for (i=0; i < stream->ts_number_audio_pids; i++)
         {
             hb_audio_t *audio = hb_ts_stream_set_audio_id_and_codec(stream, i);
-            if (audio->codec)
+            if (audio->config.in.codec)
                 hb_list_add( aTitle->list_audio, audio );
             else
             {
@@ -756,6 +757,26 @@ int hb_stream_seek( hb_stream_t * src_stream, float f )
   return 1;
 }
 
+static void set_audio_description( hb_audio_t *audio, iso639_lang_t *lang )
+{
+    /* XXX
+     * This is a duplicate of code in dvd.c - it should get factored out
+     * into a common routine. We probably should only be putting the lang
+     * code or a lang pointer into the audio config & let the common description
+     * formatting routine in scan.c do all the stuff below.
+     */
+    snprintf( audio->config.lang.description,
+              sizeof( audio->config.lang.description ), "%s (%s)",
+              strlen(lang->native_name) ? lang->native_name : lang->eng_name,
+              audio->config.in.codec == HB_ACODEC_AC3 ? "AC3" :
+                  audio->config.in.codec == HB_ACODEC_DCA ? "DTS" :
+                      audio->config.in.codec == HB_ACODEC_MPGA ? "MPEG" : "LPCM" );
+    snprintf( audio->config.lang.simple, sizeof( audio->config.lang.simple ), "%s",
+              strlen(lang->native_name) ? lang->native_name : lang->eng_name );
+    snprintf( audio->config.lang.iso639_2, sizeof( audio->config.lang.iso639_2 ),
+              "%s", lang->iso639_2);
+}
+
 static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream,
                                                        int aud_pid_index)
 {
@@ -773,7 +794,7 @@ static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream,
         if (buf[3] == 0xbd)
         {
             audio->id = 0x80bd | (aud_pid_index << 8);
-            audio->codec = HB_ACODEC_AC3;
+            audio->config.in.codec = HB_ACODEC_AC3;
             hb_log("transport stream pid 0x%x (type 0x%x) is AC-3 audio id 0x%x",
                    stream->ts_audio_pids[aud_pid_index],
                    stream->ts_audio_stream_type[1 + aud_pid_index],
@@ -784,7 +805,7 @@ static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream,
         else if ((buf[3] & 0xe0) == 0xc0)
         {
             audio->id = buf[3] | aud_pid_index;
-            audio->codec = HB_ACODEC_MPGA;
+            audio->config.in.codec = HB_ACODEC_MPGA;
             hb_log("transport stream pid 0x%x (type 0x%x) is MPEG audio id 0x%x",
                    stream->ts_audio_pids[aud_pid_index],
                    stream->ts_audio_stream_type[1 + aud_pid_index],
@@ -794,7 +815,12 @@ static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream,
         }
     }
     fseeko(stream->file_handle, cur_pos, SEEK_SET);
-    if (! audio->codec)
+    if ( audio->config.in.codec )
+    {
+               set_audio_description( audio,
+                  lang_for_code( stream->a52_info[aud_pid_index].lang_code ) );
+    }
+    else
     {
         hb_log("transport stream pid 0x%x (type 0x%x) isn't audio",
                 stream->ts_audio_pids[aud_pid_index],
@@ -811,7 +837,7 @@ static void add_audio_to_title(hb_title_t *title, int id)
     switch ( id >> 12 )
     {
         case 0x0:
-            audio->codec = HB_ACODEC_MPGA;
+            audio->config.in.codec = HB_ACODEC_MPGA;
             hb_log("add_audio_to_title: added MPEG audio stream 0x%x", id);
             break;
         case 0x2:
@@ -819,11 +845,11 @@ static void add_audio_to_title(hb_title_t *title, int id)
             free( audio );
             return;
         case 0x8:
-            audio->codec = HB_ACODEC_AC3;
+            audio->config.in.codec = HB_ACODEC_AC3;
             hb_log("add_audio_to_title: added AC3 audio stream 0x%x", id);
             break;
         case 0xa:
-            audio->codec = HB_ACODEC_LPCM;
+            audio->config.in.codec = HB_ACODEC_LPCM;
             hb_log("add_audio_to_title: added LPCM audio stream 0x%x", id);
             break;
         default:
@@ -832,6 +858,7 @@ static void add_audio_to_title(hb_title_t *title, int id)
             return;
 
     }
+    set_audio_description( audio, lang_for_code( 0 ) );
     hb_list_add( title->list_audio, audio );
 }
 
@@ -884,121 +911,6 @@ static void hb_ps_stream_find_audio_ids(hb_stream_t *stream, hb_title_t *title)
 }
 
 /***********************************************************************
- * hb_stream_update_audio
- ***********************************************************************
- *
- **********************************************************************/
-void hb_stream_update_audio(hb_stream_t *stream, hb_audio_t *audio)
-{
-       iso639_lang_t *lang;
-
-    if (stream->stream_type == hb_stream_type_transport)
-       {
-        // Find the audio stream info for this PID. The stream index is
-        // the subchannel id which is in the bottom four bits for MPEG audio
-        // and the bottom four bits of the upper byte for everything else.
-        int i = ( audio->id >= 0xd0 ? audio->id >> 8 : audio->id ) & 0xf;
-        if (i >= stream->ts_number_audio_pids)
-               {
-            hb_log("hb_stream_update_audio: no PID for audio stream 0x%x",
-                    audio->id);
-                       return;
-               }
-        if (audio->id < 0xd0)
-        {
-            /* XXX fake mpeg audio sample rate & bps */
-            stream->a52_info[i].flags = A52_STEREO;
-            stream->a52_info[i].rate = 48000 /*Hz*/;
-            stream->a52_info[i].bitrate = 384000 /*Bps*/;
-        }
-
-               lang = lang_for_code(stream->a52_info[i].lang_code);
-               if (!audio->rate)
-                       audio->rate = stream->a52_info[i].rate;
-               if (!audio->bitrate)
-                       audio->bitrate = stream->a52_info[i].bitrate;
-               if (!audio->config.a52.ac3flags)
-                       audio->config.a52.ac3flags = audio->ac3flags = stream->a52_info[i].flags;
-
-       }
-    else
-    {
-        // XXX should try to get language code from the AC3 bitstream
-        lang = lang_for_code(0x0000);
-    }
-
-       if (!audio->input_channel_layout)
-       {
-               switch( audio->ac3flags & A52_CHANNEL_MASK )
-               {
-                       /* mono sources */
-                       case A52_MONO:
-                       case A52_CHANNEL1:
-                       case A52_CHANNEL2:
-                               audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO;
-                               break;
-                       /* stereo input */
-                       case A52_CHANNEL:
-                       case A52_STEREO:
-                               audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
-                               break;
-                       /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */
-                       case A52_DOLBY:
-                               audio->input_channel_layout = HB_INPUT_CH_LAYOUT_DOLBY;
-                               break;
-                       /* 3F/2R input */
-                       case A52_3F2R:
-                               audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R;
-                               break;
-                       /* 3F/1R input */
-                       case A52_3F1R:
-                               audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R;
-                               break;
-                       /* other inputs */
-                       case A52_3F:
-                               audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F;
-                               break;
-                       case A52_2F1R:
-                               audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R;
-                               break;
-                       case A52_2F2R:
-                               audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R;
-                               break;
-                       /* unknown */
-                       default:
-                               audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
-               }
-
-               /* add in our own LFE flag if the source has LFE */
-               if (audio->ac3flags & A52_LFE)
-               {
-                       audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;
-               }
-       }
-
-       snprintf( audio->lang, sizeof( audio->lang ), "%s (%s)", strlen(lang->native_name) ? lang->native_name : lang->eng_name,
-         audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec == HB_ACODEC_MPGA ? "MPEG" : ( audio->codec == HB_ACODEC_DCA ? "DTS" : "LPCM" ) ) );
-       snprintf( audio->lang_simple, sizeof( audio->lang_simple ), "%s", strlen(lang->native_name) ? lang->native_name : lang->eng_name );
-       snprintf( audio->iso639_2, sizeof( audio->iso639_2 ), "%s", lang->iso639_2);
-
-       if ( (audio->ac3flags & A52_CHANNEL_MASK) == A52_DOLBY ) {
-               sprintf( audio->lang + strlen( audio->lang ),
-                        " (Dolby Surround)" );
-       } else {
-               sprintf( audio->lang + strlen( audio->lang ),
-                        " (%d.%d ch)",
-                       HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) +
-                       HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout),
-                       HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout));
-       }
-
-       hb_log( "stream: audio %x: lang %s, rate %d, bitrate %d, "
-            "flags = 0x%x", audio->id, audio->lang, audio->rate,
-            audio->bitrate, audio->ac3flags );
-
-}
-
-/***********************************************************************
  * hb_ts_stream_init
  ***********************************************************************
  *
@@ -1151,6 +1063,73 @@ static void decode_element_descriptors(hb_stream_t* stream, int esindx,
     }
 }
 
+/*
+ * Get the name of the stream from the type - thanks to VLC for this.
+ */
+static const char *get_stream_name (unsigned char stream_type)
+{
+    switch( stream_type )
+    {
+    case 0x01:  /* MPEG-1 video */
+    case 0x02:  /* MPEG-2 video */
+    case 0x80:  /* MPEG-2 MOTO video */
+        return("MPEG 1/2 Video");
+        break;
+    case 0x03:  /* MPEG-1 audio */
+    case 0x04:  /* MPEG-2 audio */
+        return("MPEG Audio");
+        break;
+    case 0x11:  /* MPEG4 (audio) */
+    case 0x0f:  /* ISO/IEC 13818-7 Audio with ADTS transport syntax */
+        return("MPEG-4 Audio");
+        break;
+    case 0x10:  /* MPEG4 (video) */
+        return("MPEG-4 Video");
+        break;
+    case 0x1B:  /* H264 <- check transport syntax/needed descriptor */
+        return("H.264 Video");
+        break;
+        
+    case 0x81:  /* A52 (audio) */
+        return("A52/AC-3 Audio");
+        break;
+    case 0x82:  /* DVD_SPU (sub) */
+        return("Subtitle");
+        break;
+    case 0x83:  /* LPCM (audio) */
+        return("LPCM Audio");
+        break;
+    case 0x84:  /* SDDS (audio) */
+        return("SDDS Audio");
+        break;
+    case 0x85:  /* DTS (audio) */
+        return("DTS Audio");
+        break;
+        
+    case 0x91:  /* A52 vls (audio) */
+        return("A52b/AC-3 Audio");
+        break;
+    case 0x92:  /* DVD_SPU vls (sub) */
+        return("Subtitle");
+        break;
+        
+    case 0x94:  /* SDDS (audio) */
+        return("SDDS Audio");
+        break;
+        
+    case 0xa0:  /* MSCODEC vlc (video) (fixed later) */
+        return("MSCODEC Video");
+        break;
+        
+    case 0x06:  /* PES_PRIVATE  (fixed later) */
+    case 0x12:  /* MPEG-4 generic (sub/scene/...) (fixed later) */
+    case 0xEA:  /* Privately managed ES (VC-1) (fixed later */
+    default:
+        return("Other");
+        break;
+    }
+}
+
 int decode_program_map(hb_stream_t* stream)
 {
     bitbuf_t bb;
@@ -1199,32 +1178,35 @@ int decode_program_map(hb_stream_t* stream)
                ES_info_buf[i] = get_bits(&bb, 8);
          }
 
-         if (stream_type == 0x02)
+
+         if (stream_type == 0x02 || stream_type == 0x10 || stream_type == 0x1B)
          {
-               if (stream->ts_number_video_pids <= kMaxNumberVideoPIDS)
+              /* MPEG-2/MPEG-4/H.264 */
+              if (stream->ts_number_video_pids <= kMaxNumberVideoPIDS)
                  stream->ts_number_video_pids++;
-               stream->ts_video_pids[stream->ts_number_video_pids-1] = elementary_PID;
+              stream->ts_video_pids[stream->ts_number_video_pids-1] = elementary_PID;
+              stream->ts_video_stream_type[stream->ts_number_video_pids-1] = stream_type;
          }
-      else
-      {
-        // Defined audio stream types are 0x81 for AC-3/A52 audio and 0x03
-        // for mpeg audio. But content producers seem to use other
-        // values (0x04 and 0x06 have both been observed) so at this point
-        // we say everything that isn't a video pid is audio then at the end
-        // of hb_stream_title_scan we'll figure out which are really audio
-        // by looking at the PES headers.
-        i = stream->ts_number_audio_pids;
-        if (i < kMaxNumberAudioPIDS)
-            stream->ts_number_audio_pids++;
-        stream->ts_audio_pids[i] = elementary_PID;
-        stream->ts_audio_stream_type[1 + i] = stream_type;
-
-               if (ES_info_length > 0)
-               {
-            decode_element_descriptors(stream, i, ES_info_buf, ES_info_length);
-               }
+          else
+          {
+              // Defined audio stream types are 0x81 for AC-3/A52 audio and 0x03
+              // for mpeg audio. But content producers seem to use other
+              // values (0x04 and 0x06 have both been observed) so at this point
+              // we say everything that isn't a video pid is audio then at the end
+              // of hb_stream_title_scan we'll figure out which are really audio
+              // by looking at the PES headers.
+              i = stream->ts_number_audio_pids;
+              if (i < kMaxNumberAudioPIDS)
+                  stream->ts_number_audio_pids++;
+              stream->ts_audio_pids[i] = elementary_PID;
+              stream->ts_audio_stream_type[1 + i] = stream_type;
+              
+              if (ES_info_length > 0)
+              {
+                  decode_element_descriptors(stream, i, ES_info_buf, ES_info_length);
+              }
          }
-
+          
          cur_pos += 5 /* stream header */ + ES_info_length;
 
          free(ES_info_buf);
@@ -1495,12 +1477,18 @@ static void hb_ts_stream_find_pids(hb_stream_t *stream)
        int i=0;
        for (i=0; i < stream->ts_number_video_pids; i++)
        {
-               hb_log("      0x%x (%d)", stream->ts_video_pids[i], stream->ts_video_pids[i]);
+               hb_log("      0x%x (%d) [Type %s (0x%x)]", 
+                       stream->ts_video_pids[i], stream->ts_video_pids[i],
+                       get_stream_name(stream->ts_video_stream_type[i]),
+                       stream->ts_video_stream_type[i]);
        }
        hb_log("    Audio PIDS : ");
        for (i = 0; i < stream->ts_number_audio_pids; i++)
        {
-               hb_log("      0x%x (%d)", stream->ts_audio_pids[i], stream->ts_audio_pids[i]);
+               hb_log("      0x%x (%d) [Type %s (0x%x)]", 
+                       stream->ts_audio_pids[i], stream->ts_audio_pids[i],
+                       get_stream_name(stream->ts_audio_stream_type[i]),
+                       stream->ts_audio_stream_type[i] );
        }
  }
 
@@ -1879,7 +1867,7 @@ static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf )
             // remember the pcr across calls to this routine
             stream->ts_lastpcr = pcr;
         }
-               
+
                if ( pcr == -1 )
                {
             // don't accumulate data until we get a pcr
@@ -1903,7 +1891,7 @@ static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf )
                 // so ignore the rest.
                 continue;
             }
-            if ( !start && (stream->ts_streamcont[curstream] != -1) && 
+            if ( !start && (stream->ts_streamcont[curstream] != -1) &&
                  (continuity != ( (stream->ts_streamcont[curstream] + 1) & 0xf ) ) )
                        {
                                ts_err( stream, curstream,  "continuity error: got %d expected %d",
@@ -1933,7 +1921,7 @@ static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf )
                                stream->ts_skipbad[curstream] = 0;
                        }
 
-                       // If we don't have video yet, check to see if this is an 
+                       // If we don't have video yet, check to see if this is an
             // i_frame (group of picture start)
                        if ( curstream == 0 )
             {