in vireo/internal/demux/mp4.cpp [226:290]
void parse_video_codec_info(lsmash_track_parameters_t& track_param) {
const SampleType type = SampleType::Video;
lsmash_video_summary_t* video_summary = (lsmash_video_summary_t*)tracks(type).summary.get();
if (lsmash_check_box_type_identical(video_summary->sample_type, ISOM_CODEC_TYPE_AVC1_VIDEO)) { // H.264
// SPS, PPS
const uint32_t video_cs_count = lsmash_count_codec_specific_data(tracks(type).summary.get());
THROW_IF(video_cs_count > 10, Unsafe);
for (int i = 0; i < video_cs_count; ++i) {
lsmash_codec_specific_t* cs = lsmash_get_codec_specific_data(tracks(type).summary.get(), i + 1);
CHECK(cs);
if (!(cs->format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED &&
cs->size >= 8 &&
(cs->data.unstructured[4] == 'a' &&
cs->data.unstructured[5] == 'v' &&
cs->data.unstructured[6] == 'c' &&
cs->data.unstructured[7] == 'C'))) {
continue;
}
const uint8_t* data = cs->data.unstructured;
uint16_t offset = 8;
THROW_IF(cs->size <= offset + 8, Invalid);
THROW_IF(data[offset++] != 0x01, Invalid);
offset += 3; // data[offset]: Profile (100, 110, 122, 144 etc.), data[offset + 1] = Compatibility, data[offset + 2] = Level
nalu_length_size = (data[offset++] & 0x03) + 1; // reserved (6 bits), NALU length size - 1 (2 bits)
THROW_IF(nalu_length_size != 2 && nalu_length_size != 4, Unsupported);
THROW_IF((data[offset++] & 0x1F) != 1, Invalid); // reserved (3 bits), num of SPS (5 bits)
const uint16_t sps_size = data[offset] << 8 | data[offset + 1];
THROW_IF(!sps_size, Invalid);
THROW_IF(sps_size > security::kMaxHeaderSize, Unsafe);
offset += 2;
common::Data16 sps = common::Data16(&data[offset], sps_size, nullptr);
THROW_IF(cs->size <= offset + sps_size + 2, Invalid);
offset += sps_size;
THROW_IF(data[offset++] != 1, Unsupported); // num of SPS (8 bits)
const uint16_t pps_size = data[offset] << 8 | data[offset + 1];
THROW_IF(!pps_size, Invalid);
THROW_IF(pps_size > security::kMaxHeaderSize, Unsafe);
offset += 2;
THROW_IF(offset + pps_size != cs->size && offset + pps_size + 4 != cs->size, Invalid);
common::Data16 pps = common::Data16(&data[offset], pps_size, nullptr);
if (offset + pps_size + 4 == cs->size) { // some videos have extra 4 bytes
offset += pps_size;
// data[offset] - reserved (6 bits), chroma_format (2 bits), 1=YUV420
// data[offset + 1] - reserved (5 bits), bit_depth_luma_minus8 (3 bits)
// data[offset + 2] - reserved (5 bits), bit_depth_chroma_minus8 (3 bits)
const uint8_t num_sps_ext = data[offset + 3]; // num of SPS Ext (8 bits)
THROW_IF(num_sps_ext != 0, Unsupported);
}
video.sps_pps.reset(new header::SPS_PPS(sps, pps, nalu_length_size));
video.codec = settings::Video::Codec::H264;
break; // we found the info we wanted, no need to check the rest of the codec specific data
}
} else {
if (lsmash_check_box_type_identical(video_summary->sample_type, ISOM_CODEC_TYPE_MP4V_VIDEO)) { // MPEG-4 Visual
video.codec = settings::Video::Codec::MPEG4;
} else if (lsmash_check_box_type_identical(video_summary->sample_type, QT_CODEC_TYPE_APCH_VIDEO) ||
lsmash_check_box_type_identical(video_summary->sample_type, QT_CODEC_TYPE_APCN_VIDEO) ||
lsmash_check_box_type_identical(video_summary->sample_type, QT_CODEC_TYPE_APCS_VIDEO) ||
lsmash_check_box_type_identical(video_summary->sample_type, QT_CODEC_TYPE_APCO_VIDEO) ||
lsmash_check_box_type_identical(video_summary->sample_type, QT_CODEC_TYPE_AP4H_VIDEO)) { // Apple ProRes
video.codec = settings::Video::Codec::ProRes;
}
video.sps_pps.reset(new header::SPS_PPS(common::Data16(), common::Data16(), 4)); // SPS / PPS does not exist for these codecs, mock it
}
}