// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use fidl_fuchsia_media::FormatDetails;

pub trait ElementaryStream {
    fn format_details(&self, version_ordinal: u64) -> FormatDetails;

    /// Whether _all_ chunks in the elementary stream will be marked with access unit boundaries.
    /// These are units for stream processors (e.g. for H264 decoder, NALs). When input is not in
    /// access units, the server must parse and/or buffer the bitstream.
    fn is_access_units(&self) -> bool;

    fn stream<'a>(&'a self) -> Box<dyn Iterator<Item = ElementaryStreamChunk> + 'a>;

    /// Returns the elementary stream with chunks capped at a given size. Chunks bigger than the cap
    /// will be divided into multiple chunks. Order is retained. Timestamps are not extrapolated.
    /// Access unit boundaries are corrected.
    fn capped_chunks<'a>(
        &'a self,
        max_size: usize,
    ) -> Box<dyn Iterator<Item = ElementaryStreamChunk> + 'a> {
        Box::new(self.stream().flat_map(move |chunk| CappedSizeChunks {
            src: chunk,
            offset: 0,
            max_size,
        }))
    }

    fn video_frame_count(&self) -> usize {
        self.stream()
            .filter(|chunk| match chunk.significance {
                Significance::Video(VideoSignificance::Picture) => true,
                _ => false,
            })
            .count()
    }
}

#[derive(Clone, Debug)]
pub struct ElementaryStreamChunk {
    pub start_access_unit: bool,
    pub known_end_access_unit: bool,
    pub data: Vec<u8>,
    pub significance: Significance,
    pub timestamp: Option<u64>,
}

#[derive(Copy, Clone, Debug)]
pub enum Significance {
    Video(VideoSignificance),
    Audio(AudioSignificance),
}

#[derive(Copy, Clone, Debug)]
pub enum VideoSignificance {
    Picture,
    NotPicture,
}

#[derive(Copy, Clone, Debug)]
pub enum AudioSignificance {
    PcmFrames,
    Encoded,
}

struct CappedSizeChunks {
    src: ElementaryStreamChunk,
    offset: usize,
    max_size: usize,
}

impl Iterator for CappedSizeChunks {
    type Item = ElementaryStreamChunk;
    fn next(&mut self) -> Option<Self::Item> {
        if self.offset >= self.src.data.len() {
            return None;
        }

        let len = std::cmp::min(self.src.data.len() - self.offset, self.max_size);
        let next_offset = self.offset + len;
        let is_first_subchunk = self.offset == 0;
        let is_last_subchunk = next_offset == self.src.data.len();
        let chunk = ElementaryStreamChunk {
            start_access_unit: self.src.start_access_unit && is_first_subchunk,
            known_end_access_unit: self.src.known_end_access_unit && is_last_subchunk,
            data: self.src.data[self.offset..next_offset].to_vec(),
            timestamp: if is_first_subchunk { self.src.timestamp } else { None },
            significance: self.src.significance,
        };
        self.offset = next_offset;

        Some(chunk)
    }
}

/// Wraps an elementary stream and adds sequential dummy timestamps to its chunks.
pub struct TimestampedStream<S, I> {
    pub source: S,
    pub timestamps: I,
}

impl<S, I> ElementaryStream for TimestampedStream<S, I>
where
    S: ElementaryStream,
    I: Iterator<Item = u64> + Clone,
{
    fn format_details(&self, version_ordinal: u64) -> FormatDetails {
        self.source.format_details(version_ordinal)
    }

    fn is_access_units(&self) -> bool {
        self.source.is_access_units()
    }

    fn stream<'a>(&'a self) -> Box<dyn Iterator<Item = ElementaryStreamChunk> + 'a> {
        let mut timestamps = self.timestamps.clone();
        Box::new(self.source.stream().map(move |mut chunk| {
            match chunk.significance {
                Significance::Video(VideoSignificance::Picture) => {
                    chunk.timestamp = timestamps.next();
                }
                _ => {}
            };
            chunk
        }))
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use fidl::encoding::Decodable;

    struct FakeStream {
        data: Vec<u8>,
    }

    impl ElementaryStream for FakeStream {
        fn format_details(&self, _version_ordinal: u64) -> FormatDetails {
            Decodable::new_empty()
        }

        fn is_access_units(&self) -> bool {
            true
        }

        fn stream<'a>(&'a self) -> Box<dyn Iterator<Item = ElementaryStreamChunk> + 'a> {
            Box::new(self.data.chunks(20).map(|data| ElementaryStreamChunk {
                start_access_unit: true,
                known_end_access_unit: true,
                data: data.to_vec(),
                significance: Significance::Video(VideoSignificance::Picture),
                timestamp: None,
            }))
        }
    }

    #[test]
    fn chunks_are_capped() {
        let stream = TimestampedStream {
            source: FakeStream { data: (0..).take(100).collect() },
            timestamps: 0..,
        };
        let chunk_size = 10;
        for (i, capped_chunk) in stream.capped_chunks(chunk_size).enumerate() {
            if i % 2 == 0 {
                // This is the first half of a capped chunk.
                assert!(capped_chunk.start_access_unit);
                assert_eq!(capped_chunk.timestamp, Some(i as u64 / 2));
            } else {
                // This is the second half of a capped chunk.
                assert!(capped_chunk.known_end_access_unit);

                // No subchunks other than the first should have a timestamp; if there is a
                // timestamp, we spend it on the first subchunk to keep it aligned.
                assert!(capped_chunk.timestamp.is_none());
            }

            for j in 0..chunk_size {
                assert_eq!(capped_chunk.data[j], (i * chunk_size + j) as u8);
            }
        }
    }
}
