Maybe<uint32_t> MP4Metadata::TrackTypeToGlobalTrackIndex( mozilla::TrackInfo::TrackType aType, size_t aTrackNumber) const { uint32_t tracks; auto rv = mp4parse_get_track_count(mParser.get(), &tracks); if (rv != MP4PARSE_STATUS_OK) { return Nothing(); } /* The MP4Metadata API uses a per-TrackType index of tracks, but mp4parse (and libstagefright) use a global track index. Convert the index by counting the tracks of the requested type and returning the global track index when a match is found. */ uint32_t perType = 0; for (uint32_t i = 0; i < tracks; ++i) { Mp4parseTrackInfo track_info; rv = mp4parse_get_track_info(mParser.get(), i, &track_info); if (rv != MP4PARSE_STATUS_OK) { continue; } if (TrackTypeEqual(aType, track_info.track_type)) { if (perType == aTrackNumber) { return Some(i); } perType += 1; } } return Nothing(); }
TEST(rust, MP4Metadata) { FILE* f = fopen("street.mp4", "rb"); ASSERT_TRUE(f != nullptr); // Read just the moov header to work around the parser // treating mid-box eof as an error. //read_vector reader = read_vector(f, 1061); struct stat s; ASSERT_EQ(0, fstat(fileno(f), &s)); read_vector reader = read_vector(f, s.st_size); fclose(f); mp4parse_io io = { vector_reader, &reader }; mp4parse_parser* context = mp4parse_new(&io); ASSERT_NE(nullptr, context); mp4parse_error rv = mp4parse_read(context); EXPECT_EQ(MP4PARSE_OK, rv); uint32_t tracks = 0; rv = mp4parse_get_track_count(context, &tracks); EXPECT_EQ(MP4PARSE_OK, rv); EXPECT_EQ(2U, tracks); mp4parse_free(context); }
uint32_t MP4MetadataRust::GetNumberTracks(mozilla::TrackInfo::TrackType aType) const { static LazyLogModule sLog("MP4Metadata"); uint32_t tracks = mp4parse_get_track_count(mRustState.get()); MOZ_LOG(sLog, LogLevel::Info, ("rust parser found %u tracks", tracks)); uint32_t total = 0; for (uint32_t i = 0; i < tracks; ++i) { mp4parse_track_info track_info; int32_t rv = mp4parse_get_track_info(mRustState.get(), i, &track_info); if (rv != MP4PARSE_OK) { continue; } switch (aType) { case mozilla::TrackInfo::kAudioTrack: if (track_info.track_type == MP4PARSE_TRACK_TYPE_AAC) { total += 1; } break; case mozilla::TrackInfo::kVideoTrack: if (track_info.track_type == MP4PARSE_TRACK_TYPE_H264) { total += 1; } break; default: break; } } return total; }
MP4Metadata::ResultAndTrackCount MP4Metadata::GetNumberTracks( mozilla::TrackInfo::TrackType aType) const { uint32_t tracks; auto rv = mp4parse_get_track_count(mParser.get(), &tracks); if (rv != MP4PARSE_STATUS_OK) { MOZ_LOG(gMP4MetadataLog, LogLevel::Warning, ("rust parser error %d counting tracks", rv)); return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR, RESULT_DETAIL("Rust parser error %d", rv)), MP4Metadata::NumberTracksError()}; } uint32_t total = 0; for (uint32_t i = 0; i < tracks; ++i) { Mp4parseTrackInfo track_info; rv = mp4parse_get_track_info(mParser.get(), i, &track_info); if (rv != MP4PARSE_STATUS_OK) { continue; } if (track_info.track_type == MP4PARSE_TRACK_TYPE_AUDIO) { Mp4parseTrackAudioInfo audio; auto rv = mp4parse_get_track_audio_info(mParser.get(), i, &audio); if (rv != MP4PARSE_STATUS_OK) { MOZ_LOG(gMP4MetadataLog, LogLevel::Warning, ("mp4parse_get_track_audio_info returned error %d", rv)); continue; } MOZ_DIAGNOSTIC_ASSERT(audio.sample_info_count > 0, "Must have at least one audio sample info"); if (audio.sample_info_count == 0) { return { MediaResult( NS_ERROR_DOM_MEDIA_METADATA_ERR, RESULT_DETAIL( "Got 0 audio sample info while checking number tracks")), MP4Metadata::NumberTracksError()}; } // We assume the codec of the first sample info is representative of the // whole track and skip it if we don't recognize the codec. if (audio.sample_info[0].codec_type == MP4PARSE_CODEC_UNKNOWN) { continue; } } else if (track_info.track_type == MP4PARSE_TRACK_TYPE_VIDEO) { Mp4parseTrackVideoInfo video; auto rv = mp4parse_get_track_video_info(mParser.get(), i, &video); if (rv != MP4PARSE_STATUS_OK) { MOZ_LOG(gMP4MetadataLog, LogLevel::Warning, ("mp4parse_get_track_video_info returned error %d", rv)); continue; } MOZ_DIAGNOSTIC_ASSERT(video.sample_info_count > 0, "Must have at least one video sample info"); if (video.sample_info_count == 0) { return { MediaResult( NS_ERROR_DOM_MEDIA_METADATA_ERR, RESULT_DETAIL( "Got 0 video sample info while checking number tracks")), MP4Metadata::NumberTracksError()}; } // We assume the codec of the first sample info is representative of the // whole track and skip it if we don't recognize the codec. if (video.sample_info[0].codec_type == MP4PARSE_CODEC_UNKNOWN) { continue; } } else { // Only audio and video are supported continue; } if (TrackTypeEqual(aType, track_info.track_type)) { total += 1; } } MOZ_LOG(gMP4MetadataLog, LogLevel::Info, ("%s tracks found: %u", TrackTypeToString(aType), total)); return {NS_OK, total}; }