|
|
|
@ -1382,6 +1382,95 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb, |
|
|
|
|
AVStream *st, MOVStreamContext *sc) |
|
|
|
|
{ |
|
|
|
|
int bits_per_sample, flags; |
|
|
|
|
uint16_t version = avio_rb16(pb); |
|
|
|
|
AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE); |
|
|
|
|
|
|
|
|
|
avio_rb16(pb); /* revision level */ |
|
|
|
|
avio_rb32(pb); /* vendor */ |
|
|
|
|
|
|
|
|
|
st->codec->channels = avio_rb16(pb); /* channel count */ |
|
|
|
|
st->codec->bits_per_coded_sample = avio_rb16(pb); /* sample size */ |
|
|
|
|
av_dlog(c->fc, "audio channels %d\n", st->codec->channels); |
|
|
|
|
|
|
|
|
|
sc->audio_cid = avio_rb16(pb); |
|
|
|
|
avio_rb16(pb); /* packet size = 0 */ |
|
|
|
|
|
|
|
|
|
st->codec->sample_rate = ((avio_rb32(pb) >> 16)); |
|
|
|
|
|
|
|
|
|
// Read QT version 1 fields. In version 0 these do not exist.
|
|
|
|
|
av_dlog(c->fc, "version =%d, isom =%d\n", version, c->isom); |
|
|
|
|
if (!c->isom || |
|
|
|
|
(compatible_brands && strstr(compatible_brands->value, "qt "))) { |
|
|
|
|
|
|
|
|
|
if (version == 1) { |
|
|
|
|
sc->samples_per_frame = avio_rb32(pb); |
|
|
|
|
avio_rb32(pb); /* bytes per packet */ |
|
|
|
|
sc->bytes_per_frame = avio_rb32(pb); |
|
|
|
|
avio_rb32(pb); /* bytes per sample */ |
|
|
|
|
} else if (version == 2) { |
|
|
|
|
avio_rb32(pb); /* sizeof struct only */ |
|
|
|
|
st->codec->sample_rate = av_int2double(avio_rb64(pb)); |
|
|
|
|
st->codec->channels = avio_rb32(pb); |
|
|
|
|
avio_rb32(pb); /* always 0x7F000000 */ |
|
|
|
|
st->codec->bits_per_coded_sample = avio_rb32(pb); |
|
|
|
|
|
|
|
|
|
flags = avio_rb32(pb); /* lpcm format specific flag */ |
|
|
|
|
sc->bytes_per_frame = avio_rb32(pb); |
|
|
|
|
sc->samples_per_frame = avio_rb32(pb); |
|
|
|
|
if (st->codec->codec_tag == MKTAG('l','p','c','m')) |
|
|
|
|
st->codec->codec_id = |
|
|
|
|
ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, |
|
|
|
|
flags); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch (st->codec->codec_id) { |
|
|
|
|
case AV_CODEC_ID_PCM_S8: |
|
|
|
|
case AV_CODEC_ID_PCM_U8: |
|
|
|
|
if (st->codec->bits_per_coded_sample == 16) |
|
|
|
|
st->codec->codec_id = AV_CODEC_ID_PCM_S16BE; |
|
|
|
|
break; |
|
|
|
|
case AV_CODEC_ID_PCM_S16LE: |
|
|
|
|
case AV_CODEC_ID_PCM_S16BE: |
|
|
|
|
if (st->codec->bits_per_coded_sample == 8) |
|
|
|
|
st->codec->codec_id = AV_CODEC_ID_PCM_S8; |
|
|
|
|
else if (st->codec->bits_per_coded_sample == 24) |
|
|
|
|
st->codec->codec_id = |
|
|
|
|
st->codec->codec_id == AV_CODEC_ID_PCM_S16BE ? |
|
|
|
|
AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE; |
|
|
|
|
break; |
|
|
|
|
/* set values for old format before stsd version 1 appeared */ |
|
|
|
|
case AV_CODEC_ID_MACE3: |
|
|
|
|
sc->samples_per_frame = 6; |
|
|
|
|
sc->bytes_per_frame = 2 * st->codec->channels; |
|
|
|
|
break; |
|
|
|
|
case AV_CODEC_ID_MACE6: |
|
|
|
|
sc->samples_per_frame = 6; |
|
|
|
|
sc->bytes_per_frame = 1 * st->codec->channels; |
|
|
|
|
break; |
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_QT: |
|
|
|
|
sc->samples_per_frame = 64; |
|
|
|
|
sc->bytes_per_frame = 34 * st->codec->channels; |
|
|
|
|
break; |
|
|
|
|
case AV_CODEC_ID_GSM: |
|
|
|
|
sc->samples_per_frame = 160; |
|
|
|
|
sc->bytes_per_frame = 33; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bits_per_sample = av_get_bits_per_sample(st->codec->codec_id); |
|
|
|
|
if (bits_per_sample) { |
|
|
|
|
st->codec->bits_per_coded_sample = bits_per_sample; |
|
|
|
|
sc->sample_size = (bits_per_sample >> 3) * st->codec->channels; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) |
|
|
|
|
{ |
|
|
|
|
AVStream *st; |
|
|
|
@ -1441,87 +1530,8 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) |
|
|
|
|
st->codec->codec_id = id; |
|
|
|
|
mov_parse_stsd_video(c, pb, st, sc); |
|
|
|
|
} else if (st->codec->codec_type==AVMEDIA_TYPE_AUDIO) { |
|
|
|
|
int bits_per_sample, flags; |
|
|
|
|
uint16_t version = avio_rb16(pb); |
|
|
|
|
AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE); |
|
|
|
|
|
|
|
|
|
st->codec->codec_id = id; |
|
|
|
|
avio_rb16(pb); /* revision level */ |
|
|
|
|
avio_rb32(pb); /* vendor */ |
|
|
|
|
|
|
|
|
|
st->codec->channels = avio_rb16(pb); /* channel count */ |
|
|
|
|
av_dlog(c->fc, "audio channels %d\n", st->codec->channels); |
|
|
|
|
st->codec->bits_per_coded_sample = avio_rb16(pb); /* sample size */ |
|
|
|
|
|
|
|
|
|
sc->audio_cid = avio_rb16(pb); |
|
|
|
|
avio_rb16(pb); /* packet size = 0 */ |
|
|
|
|
|
|
|
|
|
st->codec->sample_rate = ((avio_rb32(pb) >> 16)); |
|
|
|
|
|
|
|
|
|
//Read QT version 1 fields. In version 0 these do not exist.
|
|
|
|
|
av_dlog(c->fc, "version =%d, isom =%d\n",version,c->isom); |
|
|
|
|
if (!c->isom || |
|
|
|
|
(compatible_brands && strstr(compatible_brands->value, "qt "))) { |
|
|
|
|
if (version==1) { |
|
|
|
|
sc->samples_per_frame = avio_rb32(pb); |
|
|
|
|
avio_rb32(pb); /* bytes per packet */ |
|
|
|
|
sc->bytes_per_frame = avio_rb32(pb); |
|
|
|
|
avio_rb32(pb); /* bytes per sample */ |
|
|
|
|
} else if (version==2) { |
|
|
|
|
avio_rb32(pb); /* sizeof struct only */ |
|
|
|
|
st->codec->sample_rate = av_int2double(avio_rb64(pb)); /* float 64 */ |
|
|
|
|
st->codec->channels = avio_rb32(pb); |
|
|
|
|
avio_rb32(pb); /* always 0x7F000000 */ |
|
|
|
|
st->codec->bits_per_coded_sample = avio_rb32(pb); /* bits per channel if sound is uncompressed */ |
|
|
|
|
flags = avio_rb32(pb); /* lpcm format specific flag */ |
|
|
|
|
sc->bytes_per_frame = avio_rb32(pb); /* bytes per audio packet if constant */ |
|
|
|
|
sc->samples_per_frame = avio_rb32(pb); /* lpcm frames per audio packet if constant */ |
|
|
|
|
if (format == MKTAG('l','p','c','m')) |
|
|
|
|
st->codec->codec_id = ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, flags); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch (st->codec->codec_id) { |
|
|
|
|
case AV_CODEC_ID_PCM_S8: |
|
|
|
|
case AV_CODEC_ID_PCM_U8: |
|
|
|
|
if (st->codec->bits_per_coded_sample == 16) |
|
|
|
|
st->codec->codec_id = AV_CODEC_ID_PCM_S16BE; |
|
|
|
|
break; |
|
|
|
|
case AV_CODEC_ID_PCM_S16LE: |
|
|
|
|
case AV_CODEC_ID_PCM_S16BE: |
|
|
|
|
if (st->codec->bits_per_coded_sample == 8) |
|
|
|
|
st->codec->codec_id = AV_CODEC_ID_PCM_S8; |
|
|
|
|
else if (st->codec->bits_per_coded_sample == 24) |
|
|
|
|
st->codec->codec_id = |
|
|
|
|
st->codec->codec_id == AV_CODEC_ID_PCM_S16BE ? |
|
|
|
|
AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE; |
|
|
|
|
break; |
|
|
|
|
/* set values for old format before stsd version 1 appeared */ |
|
|
|
|
case AV_CODEC_ID_MACE3: |
|
|
|
|
sc->samples_per_frame = 6; |
|
|
|
|
sc->bytes_per_frame = 2*st->codec->channels; |
|
|
|
|
break; |
|
|
|
|
case AV_CODEC_ID_MACE6: |
|
|
|
|
sc->samples_per_frame = 6; |
|
|
|
|
sc->bytes_per_frame = 1*st->codec->channels; |
|
|
|
|
break; |
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_QT: |
|
|
|
|
sc->samples_per_frame = 64; |
|
|
|
|
sc->bytes_per_frame = 34*st->codec->channels; |
|
|
|
|
break; |
|
|
|
|
case AV_CODEC_ID_GSM: |
|
|
|
|
sc->samples_per_frame = 160; |
|
|
|
|
sc->bytes_per_frame = 33; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bits_per_sample = av_get_bits_per_sample(st->codec->codec_id); |
|
|
|
|
if (bits_per_sample) { |
|
|
|
|
st->codec->bits_per_coded_sample = bits_per_sample; |
|
|
|
|
sc->sample_size = (bits_per_sample >> 3) * st->codec->channels; |
|
|
|
|
} |
|
|
|
|
mov_parse_stsd_audio(c, pb, st, sc); |
|
|
|
|
} else if (st->codec->codec_type==AVMEDIA_TYPE_SUBTITLE){ |
|
|
|
|
// ttxt stsd contains display flags, justification, background
|
|
|
|
|
// color, fonts, and default styles, so fake an atom to read it
|
|
|
|
|