void parse_video_codec_info()

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
    }
  }