Loading media/extractors/mp4/MPEG4Extractor.cpp +70 −1 Original line number Diff line number Diff line Loading @@ -338,13 +338,16 @@ static const char *FourCC2MIME(uint32_t fourcc) { return MEDIA_MIMETYPE_VIDEO_HEVC; case FOURCC("ac-4"): return MEDIA_MIMETYPE_AUDIO_AC4; case FOURCC("Opus"): return MEDIA_MIMETYPE_AUDIO_OPUS; case FOURCC("twos"): case FOURCC("sowt"): return MEDIA_MIMETYPE_AUDIO_RAW; case FOURCC("alac"): return MEDIA_MIMETYPE_AUDIO_ALAC; case FOURCC("fLaC"): return MEDIA_MIMETYPE_AUDIO_FLAC; case FOURCC("av01"): return MEDIA_MIMETYPE_VIDEO_AV1; case FOURCC(".mp3"): Loading Loading @@ -1640,9 +1643,11 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC("enca"): case FOURCC("samr"): case FOURCC("sawb"): case FOURCC("Opus"): case FOURCC("twos"): case FOURCC("sowt"): case FOURCC("alac"): case FOURCC("fLaC"): case FOURCC(".mp3"): case 0x6D730055: // "ms U" mp3 audio { Loading Loading @@ -1729,6 +1734,47 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, num_channels); AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate); if (chunk_type == FOURCC("Opus")) { uint8_t opusInfo[19]; data_offset += sizeof(buffer); // Read Opus Header if (mDataSource->readAt( data_offset, opusInfo, sizeof(opusInfo)) < (ssize_t)sizeof(opusInfo)) { return ERROR_IO; } // OpusHeader must start with this magic sequence // http://wiki.xiph.org/OggOpus#ID_Header strncpy((char *)opusInfo, "OpusHead", 8); // Read Opus Specific Box values size_t opusOffset = 10; uint16_t pre_skip = U16_AT(&opusInfo[opusOffset]); uint32_t sample_rate = U32_AT(&opusInfo[opusOffset + 2]); uint16_t out_gain = U16_AT(&opusInfo[opusOffset + 6]); // Convert Opus Specific Box values. ParseOpusHeader expects // the values in LE, however MP4 stores these values as BE // https://opus-codec.org/docs/opus_in_isobmff.html#4.3.2 memcpy(&opusInfo[opusOffset], &pre_skip, sizeof(pre_skip)); memcpy(&opusInfo[opusOffset + 2], &sample_rate, sizeof(sample_rate)); memcpy(&opusInfo[opusOffset + 6], &out_gain, sizeof(out_gain)); int64_t codecDelay = 6500000; int64_t seekPreRollNs = 80000000; // Fixed 80 msec AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, opusInfo, sizeof(opusInfo)); AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_1, &codecDelay, sizeof(codecDelay)); AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2, &seekPreRollNs, sizeof(seekPreRollNs)); data_offset += sizeof(opusInfo); *offset = data_offset; CHECK_EQ(*offset, stop_offset); } if (chunk_type == FOURCC("alac")) { // See 'external/alac/ALACMagicCookieDescription.txt for the detail'. Loading Loading @@ -1766,6 +1812,29 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { CHECK_EQ(*offset, stop_offset); } if (chunk_type == FOURCC("fLaC")) { // From https://github.com/xiph/flac/blob/master/doc/isoflac.txt // 4 for mime, 4 for blockType and BlockLen, 34 for metadata uint8_t flacInfo[4 + 4 + 34]; // skipping dFla, version data_offset += sizeof(buffer) + 12; size_t flacOffset = 4; // Add flaC header mime type to CSD strncpy((char *)flacInfo, "fLaC", 4); if (mDataSource->readAt( data_offset, flacInfo + flacOffset, sizeof(flacInfo) - flacOffset) < (ssize_t)sizeof(flacInfo) - flacOffset) { return ERROR_IO; } data_offset += sizeof(flacInfo) - flacOffset; AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, flacInfo, sizeof(flacInfo)); *offset = data_offset; CHECK_EQ(*offset, stop_offset); } while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); if (err != OK) { Loading Loading
media/extractors/mp4/MPEG4Extractor.cpp +70 −1 Original line number Diff line number Diff line Loading @@ -338,13 +338,16 @@ static const char *FourCC2MIME(uint32_t fourcc) { return MEDIA_MIMETYPE_VIDEO_HEVC; case FOURCC("ac-4"): return MEDIA_MIMETYPE_AUDIO_AC4; case FOURCC("Opus"): return MEDIA_MIMETYPE_AUDIO_OPUS; case FOURCC("twos"): case FOURCC("sowt"): return MEDIA_MIMETYPE_AUDIO_RAW; case FOURCC("alac"): return MEDIA_MIMETYPE_AUDIO_ALAC; case FOURCC("fLaC"): return MEDIA_MIMETYPE_AUDIO_FLAC; case FOURCC("av01"): return MEDIA_MIMETYPE_VIDEO_AV1; case FOURCC(".mp3"): Loading Loading @@ -1640,9 +1643,11 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC("enca"): case FOURCC("samr"): case FOURCC("sawb"): case FOURCC("Opus"): case FOURCC("twos"): case FOURCC("sowt"): case FOURCC("alac"): case FOURCC("fLaC"): case FOURCC(".mp3"): case 0x6D730055: // "ms U" mp3 audio { Loading Loading @@ -1729,6 +1734,47 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, num_channels); AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate); if (chunk_type == FOURCC("Opus")) { uint8_t opusInfo[19]; data_offset += sizeof(buffer); // Read Opus Header if (mDataSource->readAt( data_offset, opusInfo, sizeof(opusInfo)) < (ssize_t)sizeof(opusInfo)) { return ERROR_IO; } // OpusHeader must start with this magic sequence // http://wiki.xiph.org/OggOpus#ID_Header strncpy((char *)opusInfo, "OpusHead", 8); // Read Opus Specific Box values size_t opusOffset = 10; uint16_t pre_skip = U16_AT(&opusInfo[opusOffset]); uint32_t sample_rate = U32_AT(&opusInfo[opusOffset + 2]); uint16_t out_gain = U16_AT(&opusInfo[opusOffset + 6]); // Convert Opus Specific Box values. ParseOpusHeader expects // the values in LE, however MP4 stores these values as BE // https://opus-codec.org/docs/opus_in_isobmff.html#4.3.2 memcpy(&opusInfo[opusOffset], &pre_skip, sizeof(pre_skip)); memcpy(&opusInfo[opusOffset + 2], &sample_rate, sizeof(sample_rate)); memcpy(&opusInfo[opusOffset + 6], &out_gain, sizeof(out_gain)); int64_t codecDelay = 6500000; int64_t seekPreRollNs = 80000000; // Fixed 80 msec AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, opusInfo, sizeof(opusInfo)); AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_1, &codecDelay, sizeof(codecDelay)); AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2, &seekPreRollNs, sizeof(seekPreRollNs)); data_offset += sizeof(opusInfo); *offset = data_offset; CHECK_EQ(*offset, stop_offset); } if (chunk_type == FOURCC("alac")) { // See 'external/alac/ALACMagicCookieDescription.txt for the detail'. Loading Loading @@ -1766,6 +1812,29 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { CHECK_EQ(*offset, stop_offset); } if (chunk_type == FOURCC("fLaC")) { // From https://github.com/xiph/flac/blob/master/doc/isoflac.txt // 4 for mime, 4 for blockType and BlockLen, 34 for metadata uint8_t flacInfo[4 + 4 + 34]; // skipping dFla, version data_offset += sizeof(buffer) + 12; size_t flacOffset = 4; // Add flaC header mime type to CSD strncpy((char *)flacInfo, "fLaC", 4); if (mDataSource->readAt( data_offset, flacInfo + flacOffset, sizeof(flacInfo) - flacOffset) < (ssize_t)sizeof(flacInfo) - flacOffset) { return ERROR_IO; } data_offset += sizeof(flacInfo) - flacOffset; AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, flacInfo, sizeof(flacInfo)); *offset = data_offset; CHECK_EQ(*offset, stop_offset); } while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); if (err != OK) { Loading