From 46d90010ba1f78b68cdd6b2ee84a51fe46ee37a8 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Sat, 20 Aug 2011 05:54:27 +0300 Subject: demux_mkv: clean up audio codec handling somewhat --- libmpdemux/demux_mkv.c | 169 +++++++++++++++++++++++-------------------------- 1 file changed, 78 insertions(+), 91 deletions(-) (limited to 'libmpdemux/demux_mkv.c') diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index 9bb98f9f6f..8cccf24889 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -1301,6 +1301,39 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track, return 0; } +static struct mkv_audio_tag { + char *id; bool prefix; uint32_t formattag; +} mkv_audio_tags[] = { + { MKV_A_MP2, 0, 0x0055 }, + { MKV_A_MP3, 0, 0x0055 }, + { MKV_A_AC3, 1, 0x2000 }, + { MKV_A_EAC3, 1, mmioFOURCC('E', 'A', 'C', '3') }, + { MKV_A_DTS, 0, 0x2001 }, + { MKV_A_PCM, 0, 0x0001 }, + { MKV_A_PCM_BE, 0, 0x0001 }, + { MKV_A_AAC_2MAIN, 0, mmioFOURCC('M', 'P', '4', 'A') }, + { MKV_A_AAC_2LC, 1, mmioFOURCC('M', 'P', '4', 'A') }, + { MKV_A_AAC_2SSR, 0, mmioFOURCC('M', 'P', '4', 'A') }, + { MKV_A_AAC_4MAIN, 0, mmioFOURCC('M', 'P', '4', 'A') }, + { MKV_A_AAC_4LC, 1, mmioFOURCC('M', 'P', '4', 'A') }, + { MKV_A_AAC_4SSR, 0, mmioFOURCC('M', 'P', '4', 'A') }, + { MKV_A_AAC_4LTP, 0, mmioFOURCC('M', 'P', '4', 'A') }, + { MKV_A_AAC, 0, mmioFOURCC('M', 'P', '4', 'A') }, + { MKV_A_VORBIS, 0, mmioFOURCC('v', 'r', 'b', 's') }, + { MKV_A_QDMC, 0, mmioFOURCC('Q', 'D', 'M', 'C') }, + { MKV_A_QDMC2, 0, mmioFOURCC('Q', 'D', 'M', '2') }, + { MKV_A_WAVPACK, 0, mmioFOURCC('W', 'V', 'P', 'K') }, + { MKV_A_TRUEHD, 0, mmioFOURCC('T', 'R', 'H', 'D') }, + { MKV_A_FLAC, 0, mmioFOURCC('f', 'L', 'a', 'C') }, + { MKV_A_REAL28, 0, mmioFOURCC('2', '8', '_', '8') }, + { MKV_A_REALATRC, 0, mmioFOURCC('a', 't', 'r', 'c') }, + { MKV_A_REALCOOK, 0, mmioFOURCC('c', 'o', 'o', 'k') }, + { MKV_A_REALDNET, 0, mmioFOURCC('d', 'n', 'e', 't') }, + { MKV_A_REALSIPR, 0, mmioFOURCC('s', 'i', 'p', 'r') }, + { NULL }, +}; + + static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, int aid) { @@ -1313,10 +1346,11 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, sh_a->title = talloc_strdup(sh_a, track->name); sh_a->default_track = track->default_track; sh_a->ds = demuxer->audio; - sh_a->wf = malloc(sizeof(*sh_a->wf)); - if (track->ms_compat && (track->private_size >= sizeof(*sh_a->wf))) { + if (track->ms_compat) { + if (track->private_size < sizeof(*sh_a->wf)) + goto error; WAVEFORMATEX *wf = (WAVEFORMATEX *) track->private_data; - sh_a->wf = realloc(sh_a->wf, track->private_size); + sh_a->wf = calloc(1, track->private_size); sh_a->wf->wFormatTag = le2me_16(wf->wFormatTag); sh_a->wf->nChannels = le2me_16(wf->nChannels); sh_a->wf->nSamplesPerSec = le2me_32(wf->nSamplesPerSec); @@ -1334,66 +1368,20 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, track->a_bps = sh_a->wf->wBitsPerSample; track->a_formattag = sh_a->wf->wFormatTag; } else { - memset(sh_a->wf, 0, sizeof(*sh_a->wf)); - if (!strcmp(track->codec_id, MKV_A_MP3) - || !strcmp(track->codec_id, MKV_A_MP2)) - track->a_formattag = 0x0055; - else if (!strncmp(track->codec_id, MKV_A_AC3, strlen(MKV_A_AC3))) - track->a_formattag = 0x2000; - else if (!strncmp(track->codec_id, MKV_A_EAC3, strlen(MKV_A_EAC3))) - track->a_formattag = mmioFOURCC('E', 'A', 'C', '3'); - else if (!strcmp(track->codec_id, MKV_A_DTS)) - track->a_formattag = 0x2001; - else if (!strcmp(track->codec_id, MKV_A_PCM) - || !strcmp(track->codec_id, MKV_A_PCM_BE)) - track->a_formattag = 0x0001; - else if (!strcmp(track->codec_id, MKV_A_AAC_2MAIN) - || !strncmp(track->codec_id, MKV_A_AAC_2LC, - strlen(MKV_A_AAC_2LC)) - || !strcmp(track->codec_id, MKV_A_AAC_2SSR) - || !strcmp(track->codec_id, MKV_A_AAC_4MAIN) - || !strncmp(track->codec_id, MKV_A_AAC_4LC, - strlen(MKV_A_AAC_4LC)) - || !strcmp(track->codec_id, MKV_A_AAC_4SSR) - || !strcmp(track->codec_id, MKV_A_AAC_4LTP) - || !strcmp(track->codec_id, MKV_A_AAC)) - track->a_formattag = mmioFOURCC('M', 'P', '4', 'A'); - else if (!strcmp(track->codec_id, MKV_A_VORBIS)) { - if (track->private_data == NULL) - return 1; - track->a_formattag = mmioFOURCC('v', 'r', 'b', 's'); - } else if (!strcmp(track->codec_id, MKV_A_QDMC)) - track->a_formattag = mmioFOURCC('Q', 'D', 'M', 'C'); - else if (!strcmp(track->codec_id, MKV_A_QDMC2)) - track->a_formattag = mmioFOURCC('Q', 'D', 'M', '2'); - else if (!strcmp(track->codec_id, MKV_A_WAVPACK)) - track->a_formattag = mmioFOURCC('W', 'V', 'P', 'K'); - else if (!strcmp(track->codec_id, MKV_A_TRUEHD)) - track->a_formattag = mmioFOURCC('T', 'R', 'H', 'D'); - else if (!strcmp(track->codec_id, MKV_A_FLAC)) { - if (track->private_data == NULL || track->private_size == 0) { - mp_tmsg(MSGT_DEMUX, MSGL_WARN, - "[mkv] FLAC track does not contain valid headers.\n"); - return 1; + sh_a->wf = calloc(1, sizeof(*sh_a->wf)); + for (int i = 0; ; i++) { + struct mkv_audio_tag *t = mkv_audio_tags + i; + if (t->id == NULL) + goto error; + if (t->prefix) { + if (!bstr_startswith0(bstr(track->codec_id), t->id)) + continue; + } else { + if (strcmp(track->codec_id, t->id)) + continue; } - track->a_formattag = mmioFOURCC('f', 'L', 'a', 'C'); - } else if (track->private_size >= RAPROPERTIES4_SIZE) { - if (!strcmp(track->codec_id, MKV_A_REAL28)) - track->a_formattag = mmioFOURCC('2', '8', '_', '8'); - else if (!strcmp(track->codec_id, MKV_A_REALATRC)) - track->a_formattag = mmioFOURCC('a', 't', 'r', 'c'); - else if (!strcmp(track->codec_id, MKV_A_REALCOOK)) - track->a_formattag = mmioFOURCC('c', 'o', 'o', 'k'); - else if (!strcmp(track->codec_id, MKV_A_REALDNET)) - track->a_formattag = mmioFOURCC('d', 'n', 'e', 't'); - else if (!strcmp(track->codec_id, MKV_A_REALSIPR)) - track->a_formattag = mmioFOURCC('s', 'i', 'p', 'r'); - } else { - mp_tmsg(MSGT_DEMUX, MSGL_WARN, "[mkv] Unknown/unsupported audio " - "codec ID '%s' for track %u or missing/faulty\n[mkv] " - "private codec data.\n", track->codec_id, track->tnum); - free_sh_audio(demuxer, track->id); - return 1; + track->a_formattag = t->formattag; + break; } } @@ -1441,8 +1429,7 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, sh_a->wf->nAvgBytesPerSec = 16000; sh_a->wf->nBlockAlign = 1024; - if (!strcmp(track->codec_id, MKV_A_AAC) - && (NULL != track->private_data)) { + if (!strcmp(track->codec_id, MKV_A_AAC) && track->private_data) { sh_a->codecdata = malloc(track->private_size); memcpy(sh_a->codecdata, track->private_data, track->private_size); sh_a->codecdata_len = track->private_size; @@ -1480,13 +1467,19 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, sh_a->codecdata_len = 2; track->default_duration = 1024.0 / sh_a->samplerate; } - } else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's')) { /* VORBIS */ - sh_a->wf->cbSize = track->private_size; - sh_a->wf = realloc(sh_a->wf, sizeof(*sh_a->wf) + sh_a->wf->cbSize); - memcpy((unsigned char *) (sh_a->wf + 1), track->private_data, - sh_a->wf->cbSize); - } else if (track->private_size >= RAPROPERTIES4_SIZE - && !strncmp(track->codec_id, MKV_A_REALATRC, 7)) { + } else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's')) { + /* VORBIS */ + if (track->private_size == 0 || track->ms_compat && !sh_a->wf->cbSize) + goto error; + if (!track->ms_compat) { + sh_a->wf->cbSize = track->private_size; + sh_a->wf = realloc(sh_a->wf, sizeof(*sh_a->wf) + sh_a->wf->cbSize); + memcpy((unsigned char *) (sh_a->wf + 1), track->private_data, + sh_a->wf->cbSize); + } + } else if (!strncmp(track->codec_id, MKV_A_REALATRC, 7)) { + if (track->private_size < RAPROPERTIES4_SIZE) + goto error; /* Common initialization for all RealAudio codecs */ unsigned char *src = track->private_data; int codecdata_length, version; @@ -1520,30 +1513,19 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, case mmioFOURCC('a', 't', 'r', 'c'): sh_a->wf->nAvgBytesPerSec = atrc_fl2bps[flavor]; sh_a->wf->nBlockAlign = track->sub_packet_size; - track->audio_buf = - malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = - malloc(track->sub_packet_h * sizeof(double)); - break; + goto audiobuf; case mmioFOURCC('c', 'o', 'o', 'k'): sh_a->wf->nAvgBytesPerSec = cook_fl2bps[flavor]; sh_a->wf->nBlockAlign = track->sub_packet_size; - track->audio_buf = - malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = - malloc(track->sub_packet_h * sizeof(double)); - break; + goto audiobuf; case mmioFOURCC('s', 'i', 'p', 'r'): sh_a->wf->nAvgBytesPerSec = sipr_fl2bps[flavor]; sh_a->wf->nBlockAlign = track->coded_framesize; - track->audio_buf = - malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = - malloc(track->sub_packet_h * sizeof(double)); - break; + goto audiobuf; case mmioFOURCC('2', '8', '_', '8'): sh_a->wf->nAvgBytesPerSec = 3600; sh_a->wf->nBlockAlign = track->coded_framesize; + audiobuf: track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size); track->audio_timestamp = @@ -1559,7 +1541,7 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, free(sh_a->wf); sh_a->wf = NULL; - if (track->a_formattag == mmioFOURCC('f', 'L', 'a', 'C')) { + if (!track->ms_compat) { ptr = track->private_data; size = track->private_size; } else { @@ -1578,13 +1560,18 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track, memcpy(sh_a->codecdata, ptr, size); } } else if (track->a_formattag == mmioFOURCC('W', 'V', 'P', 'K') || track->a_formattag == mmioFOURCC('T', 'R', 'H', 'D')) { /* do nothing, still works */ - } else if (!track->ms_compat - || (track->private_size < sizeof(*sh_a->wf))) { - free_sh_audio(demuxer, track->id); - return 1; + } else if (!track->ms_compat) { + goto error; } return 0; + + error: + mp_tmsg(MSGT_DEMUX, MSGL_WARN, "[mkv] Unknown/unsupported audio " + "codec ID '%s' for track %u or missing/faulty\n[mkv] " + "private codec data.\n", track->codec_id, track->tnum); + free_sh_audio(demuxer, track->id); + return 1; } static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track, -- cgit v1.2.3