pub fn track_info(mp4: &MP4) -> Vec<TrackInfo> {
    let mut v = Vec::new();

    let movie = mp4.movie();
    let mvhd = movie.movie_header();

    for track in &movie.tracks() {
        let mut info = TrackInfo::default();

        let tkhd = track.track_header();
        info.id = tkhd.track_id;
        info.duration = Duration::from_millis((1000 * tkhd.duration.0) / (mvhd.timescale as u64));

        let mdia = track.media();

        let mdhd = mdia.media_header();
        info.duration = Duration::from_millis((1000 * mdhd.duration.0) / (mdhd.timescale as u64));
        info.language = mdhd.language;

        let hdlr = mdia.handler();
        info.track_type = hdlr.handler_type.to_string();

        let stbl = mdia.media_info().sample_table();
        info.size = stbl.sample_size().iter().fold(0, |acc: u64, sz| acc + sz as u64);

        info.name = first_box!(track, UserDataBox)
            .and_then(|b| first_box!(b, NameBox))
            .map(|n| n.name.clone());

        let stsd = stbl.sample_description();
        if let Some(avc1) = first_box!(stsd.entries, AvcSampleEntry) {
            let mut avc1_info = avc1.track_info();
            if avc1_info.frame_rate == 0f64 {
                let sample_count = stbl.sample_size().count;
                let timescale = std::cmp::max(1000, mdhd.timescale) as f64;
                let fr = sample_count as f64 / (mdhd.duration.0 as f64 / timescale);
                log::debug!("track::track_info: avcc.framerate == 0, estimate: {}", fr);
                avc1_info.frame_rate = fr;
            }
            avc1_info.frame_rate = (avc1_info.frame_rate * 1000.0).round() / 1000.0;
            info.specific_info = SpecificTrackInfo::VideoTrackInfo(avc1_info);
        } else if let Some(hevc) = first_box!(stsd.entries, HEVCSampleEntry) {
            let mut hevc_info = hevc.track_info();
            if hevc_info.frame_rate == 0f64 {
                let sample_count = stbl.sample_size().count;
                let timescale = std::cmp::max(1000, mdhd.timescale) as f64;
                let fr = sample_count as f64 / (mdhd.duration.0 as f64 / timescale);
                log::debug!("track::track_info: hvcc.framerate == 0, estimate: {}", fr);
                hevc_info.frame_rate = fr;
            }
            hevc_info.frame_rate = (hevc_info.frame_rate * 1000.0).round() / 1000.0;
            info.specific_info = SpecificTrackInfo::VideoTrackInfo(hevc_info);
        } else if let Some(ac3) = first_box!(stsd.entries, Ac3SampleEntry) {
            let mut ac3 = ac3.track_info();
            if ac3.avg_bitrate.is_none() && info.duration.as_secs() > 0 {
                ac3.avg_bitrate = Some((8 * info.size / info.duration.as_secs()) as u32);
            }
            info.specific_info = SpecificTrackInfo::AudioTrackInfo(ac3);
        } else if let Some(aac) = first_box!(stsd.entries, AacSampleEntry) {
            let mut aac = aac.track_info();
            if aac.avg_bitrate.is_none() && info.duration.as_secs() > 0 {
                aac.avg_bitrate = Some((8 * info.size / info.duration.as_secs()) as u32);
            }
            info.specific_info = SpecificTrackInfo::AudioTrackInfo(aac);
        } else {
            let id = stsd
                .entries
                .iter()
                .next()
                .map(|e| e.fourcc().to_string())
                .unwrap_or("unkn".to_string());
            let sp_info = match id.as_str() {
                "tx3g" => {
                    SpecificTrackInfo::SubtitleTrackInfo(SubtitleTrackInfo {
                        codec_id:   id.to_string(),
                        codec_name: Some(String::from("3GPP Timed Text")),
                    })
                },
                "stpp" | "sbtt" => {
                    SpecificTrackInfo::SubtitleTrackInfo(SubtitleTrackInfo {
                        codec_id:   id.to_string(),
                        codec_name: None,
                    })
                },
                _ => {
                    SpecificTrackInfo::UnknownTrackInfo(UnknownTrackInfo {
                        codec_id:   id,
                        codec_name: None,
                    })
                },
            };
            info.specific_info = sp_info;
        }

        v.push(info)
    }

    v
}
/// Extract general track information for all tracks in the movie.
Extract general track information for all tracks in the movie.
Extract general track information for all tracks in the movie .
pub fn track_info(mp4: &MP4) -> Vec<TrackInfo> {
    let mut v = Vec::new();
    let movie = mp4.movie();
    let mvhd = movie.movie_header();
    for track in &movie.tracks() {
        let mut info = TrackInfo::default();
        let tkhd = track.track_header();
        info.id = tkhd.track_id;
        info.duration = Duration::from_millis((1000 * tkhd.duration.0) / (mvhd.timescale as u64));
        let mdia = track.media();
        let mdhd = mdia.media_header();
        info.duration = Duration::from_millis((1000 * mdhd.duration.0) / (mdhd.timescale as u64));
        info.language = mdhd.language;
        let hdlr = mdia.handler();
        info.track_type = hdlr.handler_type.to_string();
        let stbl = mdia.media_info().sample_table();
        info.size = stbl.sample_size().iter().fold(0, |acc: u64, sz| acc + sz as u64);
        info.name = first_box!(track, UserDataBox)
            .and_then(|b| first_box!(b, NameBox))
            .map(|n| n.name.clone());
        let stsd = stbl.sample_description();
        if let Some(avc1) = first_box!(stsd.entries, AvcSampleEntry) {
            let mut avc1_info = avc1.track_info();
            if avc1_info.frame_rate == 0f64 {
                let sample_count = stbl.sample_size().count;
                let timescale = std::cmp::max(1000, mdhd.timescale) as f64;
                let fr = sample_count as f64 / (mdhd.duration.0 as f64 / timescale);
                log::debug!("track::track_info: avcc.framerate == 0, estimate: {}", fr);
                avc1_info.frame_rate = fr;
            }
            avc1_info.frame_rate = (avc1_info.frame_rate * 1000.0).round() / 1000.0;
            info.specific_info = SpecificTrackInfo::VideoTrackInfo(avc1_info);
        } else if let Some(hevc) = first_box!(stsd.entries, HEVCSampleEntry) {
            let mut hevc_info = hevc.track_info();
            if hevc_info.frame_rate == 0f64 {
                let sample_count = stbl.sample_size().count;
                let timescale = std::cmp::max(1000, mdhd.timescale) as f64;
                let fr = sample_count as f64 / (mdhd.duration.0 as f64 / timescale);
                log::debug!("track::track_info: hvcc.framerate == 0, estimate: {}", fr);
                hevc_info.frame_rate = fr;
            }
            hevc_info.frame_rate = (hevc_info.frame_rate * 1000.0).round() / 1000.0;
            info.specific_info = SpecificTrackInfo::VideoTrackInfo(hevc_info);
        } else if let Some(ac3) = first_box!(stsd.entries, Ac3SampleEntry) {
            let mut ac3 = ac3.track_info();
            if ac3.avg_bitrate.is_none() && info.duration.as_secs() > 0 {
                ac3.avg_bitrate = Some((8 * info.size / info.duration.as_secs()) as u32);
            }
            info.specific_info = SpecificTrackInfo::AudioTrackInfo(ac3);
        } else if let Some(aac) = first_box!(stsd.entries, AacSampleEntry) {
            let mut aac = aac.track_info();
            if aac.avg_bitrate.is_none() && info.duration.as_secs() > 0 {
                aac.avg_bitrate = Some((8 * info.size / info.duration.as_secs()) as u32);
            }
            info.specific_info = SpecificTrackInfo::AudioTrackInfo(aac);
        } else {
            let id = stsd
                .entries
                .iter()
                .next()
                .map(|e| e.fourcc().to_string())
                .unwrap_or("unkn".to_string());
            let sp_info = match id.as_str() {
                "tx3g" => {
                    SpecificTrackInfo::SubtitleTrackInfo(SubtitleTrackInfo {
                        codec_id:   id.to_string(),
                        codec_name: Some(String::from("3GPP Timed Text")),
                    })
                },
                "stpp" | "sbtt" => {
                    SpecificTrackInfo::SubtitleTrackInfo(SubtitleTrackInfo {
                        codec_id:   id.to_string(),
                        codec_name: None,
                    })
                },
                _ => {
                    SpecificTrackInfo::UnknownTrackInfo(UnknownTrackInfo {
                        codec_id:   id,
                        codec_name: None,
                    })
                },
            };
            info.specific_info = sp_info;
        }
        v.push(info)
    }
    v
}
pub fn track_info ( mp4 : & MP4 ) -> Vec < TrackInfo > { let mut v = Vec :: new ( ) ; let movie = mp4 . movie ( ) ; let mvhd = movie . movie_header ( ) ; for track in & movie . tracks ( ) { let mut info = TrackInfo :: default ( ) ; let tkhd = track . track_header ( ) ; info . id = tkhd . track_id ; info . duration = Duration :: from_millis ( ( 1000 * tkhd . duration . 0 ) / ( mvhd . timescale as u64 ) ) ; let mdia = track . media ( ) ; let mdhd = mdia . media_header ( ) ; info . duration = Duration :: from_millis ( ( 1000 * mdhd . duration . 0 ) / ( mdhd . timescale as u64 ) ) ; info . language = mdhd . language ; let hdlr = mdia . handler ( ) ; info . track_type = hdlr . handler_type . to_string ( ) ; let stbl = mdia . media_info ( ) . sample_table ( ) ; info . size = stbl . sample_size ( ) . iter ( ) . fold ( 0 , | acc : u64 , sz | acc + sz as u64 ) ; info . name = first_box ! ( track UserDataBox ) . and_then ( | b | first_box ! ( b NameBox ) ) . map ( | n | n . name . clone ( ) ) ; let stsd = stbl . sample_description ( ) ; if let Some ( avc1 ) = first_box ! ( stsd entries AvcSampleEntry ) { let mut avc1_info = avc1 . track_info ( ) ; if avc1_info . frame_rate == 0f64 { let sample_count = stbl . sample_size ( ) . count ; let timescale = std :: cmp :: max ( 1000 , mdhd . timescale ) as f64 ; let fr = sample_count as f64 / ( mdhd . duration . 0 as f64 / timescale ) ; log :: debug ! ( " " fr ) ; avc1_info . frame_rate = fr ; } avc1_info . frame_rate = ( avc1_info . frame_rate * 1000.0 ) . round ( ) / 1000.0 ; info . specific_info = SpecificTrackInfo :: VideoTrackInfo ( avc1_info ) ; } else if let Some ( hevc ) = first_box ! ( stsd entries HEVCSampleEntry ) { let mut hevc_info = hevc . track_info ( ) ; if hevc_info . frame_rate == 0f64 { let sample_count = stbl . sample_size ( ) . count ; let timescale = std :: cmp :: max ( 1000 , mdhd . timescale ) as f64 ; let fr = sample_count as f64 / ( mdhd . duration . 0 as f64 / timescale ) ; log :: debug ! ( " " fr ) ; hevc_info . frame_rate = fr ; } hevc_info . frame_rate = ( hevc_info . frame_rate * 1000.0 ) . round ( ) / 1000.0 ; info . specific_info = SpecificTrackInfo :: VideoTrackInfo ( hevc_info ) ; } else if let Some ( ac3 ) = first_box ! ( stsd entries Ac3SampleEntry ) { let mut ac3 = ac3 . track_info ( ) ; if ac3 . avg_bitrate . is_none ( ) && info . duration . as_secs ( ) > 0 { ac3 . avg_bitrate = Some ( ( 8 * info . size / info . duration . as_secs ( ) ) as u32 ) ; } info . specific_info = SpecificTrackInfo :: AudioTrackInfo ( ac3 ) ; } else if let Some ( aac ) = first_box ! ( stsd entries AacSampleEntry ) { let mut aac = aac . track_info ( ) ; if aac . avg_bitrate . is_none ( ) && info . duration . as_secs ( ) > 0 { aac . avg_bitrate = Some ( ( 8 * info . size / info . duration . as_secs ( ) ) as u32 ) ; } info . specific_info = SpecificTrackInfo :: AudioTrackInfo ( aac ) ; } else { let id = stsd . entries . iter ( ) . next ( ) . map ( | e | e . fourcc ( ) . to_string ( ) ) . unwrap_or ( " " . to_string ( ) ) ; let sp_info = match id . as_str ( ) { " " => { SpecificTrackInfo :: SubtitleTrackInfo ( SubtitleTrackInfo { codec_id : id . to_string ( ) , codec_name : Some ( String :: from ( " " ) ) , } ) } , " " | " " => { SpecificTrackInfo :: SubtitleTrackInfo ( SubtitleTrackInfo { codec_id : id . to_string ( ) , codec_name : None , } ) } , _ => { SpecificTrackInfo :: UnknownTrackInfo ( UnknownTrackInfo { codec_id : id , codec_name : None , } ) } , } ; info . specific_info = sp_info ; } v . push ( info ) } v }
Extract general track information for all tracks in the movie.
Extract general track information for all tracks in the movie .
mp4
&MP4
mp4
&MP4