# HG changeset patch # User mosu # Date 1063193980 0 # Node ID 98681fdabf799088dc7d82c3440d794b84780072 # Parent 60f58eadd6661e68cc1a2d7139b8545d2aca3673 Support for Quicktime stuff in Matroska (e.g. Sorenson, QDesign Music codecs etc.). diff -r 60f58eadd666 -r 98681fdabf79 libmpdemux/demux_mkv.cpp --- 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 @@ -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 seekheads_to_parse; vector 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; diff -r 60f58eadd666 -r 98681fdabf79 libmpdemux/matroska.h --- 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"