changeset 10844:98681fdabf79

Support for Quicktime stuff in Matroska (e.g. Sorenson, QDesign Music codecs etc.).
author mosu
date Wed, 10 Sep 2003 11:39:40 +0000
parents 60f58eadd666
children 71db96cf88d4
files libmpdemux/demux_mkv.cpp libmpdemux/matroska.h
diffstat 2 files changed, 117 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/demux_mkv.cpp	Mon Sep 08 17:12:31 2003 +0000
+++ b/libmpdemux/demux_mkv.cpp	Wed Sep 10 11:39:40 2003 +0000
@@ -17,6 +17,7 @@
 
 #include "../subreader.h"
 #include "../libvo/sub.h"
+
 }
 
 #include <vector>
@@ -168,6 +169,10 @@
   int rm_seqnum, rv_kf_base, rv_kf_pts;
   float rv_pts;                 // previous video timestamp
   float ra_pts;                 // previous audio timestamp
+
+  // Stuff for QuickTime
+  bool fix_i_bps;
+  float qt_last_a_pts;
 } mkv_track_t;
 
 typedef struct mkv_demuxer {
@@ -277,6 +282,30 @@
   uint32_t fourcc3;             // fourcc
 } real_audio_v5_props_t;
 
+// I have to (re)define this struct here because g++ will not compile
+// components.h from the qtsdk if I include it.
+typedef struct {
+  uint32_t id_size;
+  uint32_t codec_type;
+  uint32_t reserved1;
+  uint16_t reserved2;
+  uint16_t data_reference_index;
+  uint16_t version;
+  uint16_t revision;
+  uint32_t vendor;
+  uint32_t temporal_quality;
+  uint32_t spatial_quality;
+  uint16_t width;
+  uint16_t height;
+  uint32_t horizontal_resolution; // 32bit fixed-point number
+  uint32_t vertical_resolution; // 32bit fixed-point number
+  uint32_t data_size;
+  uint16_t frame_count;
+  char compressor_name[32];
+  uint16_t depth;
+  uint16_t color_table_id;
+} qt_image_description_t;
+
 #if __GNUC__ == 2
 #pragma pack()
 #else
@@ -623,7 +652,8 @@
           else if (!strcmp(t->codec_id, MKV_A_DTS))
             // uses same format tag as AC3, only supported with -hwac3
             t->a_formattag = 0x2000;
-          else if (!strcmp(t->codec_id, MKV_A_PCM))
+          else if (!strcmp(t->codec_id, MKV_A_PCM) ||
+                   !strcmp(t->codec_id, MKV_A_PCM_BE))
             t->a_formattag = 0x0001;
           else if (!strcmp(t->codec_id, MKV_A_AAC_2MAIN) ||
                    !strcmp(t->codec_id, MKV_A_AAC_2LC) ||
@@ -686,6 +716,9 @@
               t->a_formattag = mmioFOURCC('d', 'n', 'e', 't');
             else if (!strcmp(t->codec_id, MKV_A_REALSIPR))
               t->a_formattag = mmioFOURCC('s', 'i', 'p', 'r');
+          } else if (!strcmp(t->codec_id, MKV_A_QDMC) ||
+                     !strcmp(t->codec_id, MKV_A_QDMC2)) {
+            ;
           } else {
             mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Unknown/unsupported audio "
                    "codec ID '%s' for track %u or missing/faulty private "
@@ -706,12 +739,6 @@
           continue;
         }
 
-        if (t->a_formattag == 0) {
-          mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] The audio format tag was not "
-                 "set for track %u.\n", t->tnum);
-          continue;
-        }
-
         // This track seems to be ok.
         t->ok = 1;
         mp_msg(MSGT_DEMUX, MSGL_INFO, "[mkv] Track ID %u: audio (%s), -aid "
@@ -1049,6 +1076,7 @@
   vector<uint64_t> seekheads_to_parse;
   vector<uint64_t> cues_to_parse;
   int64_t current_pos;
+  qt_image_description_t *idesc;
 
 #ifdef USE_ICONV
   subcp_open();
@@ -1470,6 +1498,7 @@
   if (track) {
     BITMAPINFOHEADER *bih;
 
+    idesc = NULL;
     bih = (BITMAPINFOHEADER *)calloc(1, track->private_size);
     if (bih == NULL) {
       free_mkv_demuxer(mkv_d);
@@ -1534,6 +1563,31 @@
           memset(&dst[8], 0, 4);
         track->realmedia = true;
 
+#if defined(USE_QTX_CODECS)
+      } else if ((track->private_size >= sizeof(qt_image_description_t)) &&
+                 (!strcmp(track->codec_id, MKV_V_QUICKTIME))) {
+        idesc = (qt_image_description_t *)track->private_data;
+        idesc->id_size = get_uint32_be(&idesc->id_size);
+        idesc->codec_type = get_uint32(&idesc->codec_type);
+        idesc->version = get_uint16_be(&idesc->version);
+        idesc->revision = get_uint16_be(&idesc->revision);
+        idesc->vendor = get_uint32_be(&idesc->vendor);
+        idesc->temporal_quality = get_uint32_be(&idesc->temporal_quality);
+        idesc->spatial_quality = get_uint32_be(&idesc->spatial_quality);
+        idesc->width = get_uint16_be(&idesc->width);
+        idesc->height = get_uint16_be(&idesc->height);
+        idesc->horizontal_resolution =
+          get_uint32_be(&idesc->horizontal_resolution);
+        idesc->vertical_resolution =
+          get_uint32_be(&idesc->vertical_resolution);
+        idesc->data_size = get_uint32_be(&idesc->data_size);
+        idesc->frame_count = get_uint16_be(&idesc->frame_count);
+        idesc->depth = get_uint16_be(&idesc->depth);
+        idesc->color_table_id = get_uint16_be(&idesc->color_table_id);
+        bih->biPlanes = 1;
+        bih->biCompression = idesc->codec_type;
+#endif // defined(USE_QTX_CODECS)
+
       } else {
         mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Unknown/unsupported CodecID "
                "(%s) or missing/bad CodecPrivate data (track %u).\n",
@@ -1556,6 +1610,8 @@
       sh_v->disp_w = track->v_width;
       sh_v->disp_h = track->v_height;
       sh_v->aspect = (float)track->v_dwidth / (float)track->v_dheight;
+      if (idesc != NULL)
+        sh_v->ImageDesc = idesc;
       mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Aspect: %f\n", sh_v->aspect);
 
       demuxer->video->id = track->tnum;
@@ -1642,10 +1698,30 @@
       sh_a->wf->wBitsPerSample = 0;
       sh_a->samplesize = 0;
 
-    } else if (!strcmp(track->codec_id, MKV_A_PCM)) {
+    } else if (!strcmp(track->codec_id, MKV_A_PCM) ||
+               !strcmp(track->codec_id, MKV_A_PCM_BE)) {
       sh_a->wf->nAvgBytesPerSec = sh_a->channels * sh_a->samplerate * 2;
       sh_a->wf->nBlockAlign = sh_a->wf->nAvgBytesPerSec;
       sh_a->wf->wBitsPerSample = track->a_bps;
+      if (!strcmp(track->codec_id, MKV_A_PCM_BE))
+        sh_a->format = mmioFOURCC('t', 'w', 'o', 's');
+
+    } else if (!strcmp(track->codec_id, MKV_A_QDMC) ||
+               !strcmp(track->codec_id, MKV_A_QDMC2)) {
+      sh_a->wf->wBitsPerSample = track->a_bps;
+      sh_a->wf->nAvgBytesPerSec = 16000;
+      sh_a->wf->nBlockAlign = 1486;
+      track->fix_i_bps = true;
+      track->qt_last_a_pts = 0.0;
+      if (track->private_data != NULL) {
+        sh_a->codecdata = (unsigned char *)calloc(track->private_size, 1);
+        memcpy(sh_a->codecdata, track->private_data, track->private_size);
+        sh_a->codecdata_len = track->private_size;
+      }
+      if (!strcmp(track->codec_id, MKV_A_QDMC))
+        sh_a->format = mmioFOURCC('Q', 'D', 'M', 'C');
+      else
+        sh_a->format = mmioFOURCC('Q', 'D', 'M', '2');
 
     } else if (track->a_formattag == mmioFOURCC('M', 'P', '4', 'A')) {
       int profile, srate_idx;
@@ -2041,6 +2117,31 @@
                 else if (mkv_d->v_skip_to_keyframe)
                   use_this_block = false;
 
+                if (mkv_d->audio->fix_i_bps && use_this_block) {
+                  uint32_t i, sum;
+                  sh_audio_t *sh;
+
+                  for (i = 0, sum = 0; i < kblock->NumberFrames(); i++) {
+                    DataBuffer &data = kblock->GetBuffer(i);
+                    sum += data.Size();
+                  }
+                  sh = (sh_audio_t *)ds->sh;
+                  if (block_duration != -1) {
+                    sh->i_bps = sum * 1000 / block_duration;
+                    mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Changed i_bps to %d.\n",
+                           sh->i_bps);
+                    mkv_d->audio->fix_i_bps = false;
+                  } else if (mkv_d->audio->qt_last_a_pts == 0.0)
+                    mkv_d->audio->qt_last_a_pts = current_pts;
+                  else if (mkv_d->audio->qt_last_a_pts != current_pts) {
+                    sh->i_bps = (int)(sum / (current_pts -
+                                             mkv_d->audio->qt_last_a_pts));
+                    mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Changed i_bps to %d.\n",
+                           sh->i_bps);
+                    mkv_d->audio->fix_i_bps = false;
+                  }
+                }
+
               } else if ((current_pts * 1000) < mkv_d->skip_to_timecode)
                 use_this_block = false;
 
--- a/libmpdemux/matroska.h	Mon Sep 08 17:12:31 2003 +0000
+++ b/libmpdemux/matroska.h	Wed Sep 10 11:39:40 2003 +0000
@@ -19,6 +19,7 @@
 #define MKV_A_DTS        "A_DTS"
 #define MKV_A_MP3        "A_MPEG/L3"
 #define MKV_A_PCM        "A_PCM/INT/LIT"
+#define MKV_A_PCM_BE     "A_PCM/INT/BIG"
 #define MKV_A_VORBIS     "A_VORBIS"
 #define MKV_A_ACM        "A_MS/ACM"
 #define MKV_A_REAL28     "A_REAL/28_8"
@@ -26,12 +27,19 @@
 #define MKV_A_REALCOOK   "A_REAL/COOK"
 #define MKV_A_REALDNET   "A_REAL/DNET"
 #define MKV_A_REALSIPR   "A_REAL/SIPR"
+#define MKV_A_QDMC       "A_QDESIGNMUSIC"
+#define MKV_A_QDMC2      "A_QDESIGNMUSIC/V2"
 
 #define MKV_V_MSCOMP     "V_MS/VFW/FOURCC"
 #define MKV_V_REALV10    "V_REAL/RV10"
 #define MKV_V_REALV20    "V_REAL/RV20"
 #define MKV_V_REALV30    "V_REAL/RV30"
 #define MKV_V_REALV40    "V_REAL/RV40"
+#define MKV_V_SORENSONV1 "V_SORENSON/V1"
+#define MKV_V_SORENSONV2 "V_SORENSON/V2"
+#define MKV_V_SORENSONV3 "V_SORENSON/V3"
+#define MKV_V_CINEPAK    "V_CINEPAK"
+#define MKV_V_QUICKTIME  "V_QUICKTIME"
 
 #define MKV_S_TEXTASCII  "S_TEXT/ASCII"
 #define MKV_S_TEXTUTF8   "S_TEXT/UTF8"