pub fn push_gst_buffer(&mut self, buffer: &gst::Buffer, lower_to_keep: usize) -> usize {
        if self.sample_duration == 0 {
            debug!("push_gst_buffer sample_duration is null");
            return 0;
        }

        let buffer_sample_len = buffer.get_size() / self.bytes_per_sample / self.channels;

        // Unfortunately, we can't rely on buffer_pts to figure out
        // the exact position in the segment. Some streams use a pts
        // value which is a rounded value to e.g ms and correct
        // the shift every n samples.
        // After an accurate seek, the buffer pts seems reliable,
        // however after a inaccurate seek, we get a rounded value.
        // The strategy here is to consider that each incoming buffer
        // in the same segment comes after last buffer (we might need
        // to check buffer drops for this) and in case of a new segment
        // we'll rely on the inaccurate pts value...

        if self.is_new_segment {
            self.segment_lower = (buffer.get_pts().unwrap() / self.sample_duration) as usize;
            self.last_buffer_upper = self.segment_lower;
            self.is_new_segment = false;
        }

        let incoming_lower = self.last_buffer_upper;
        let incoming_upper = incoming_lower + buffer_sample_len;

        // Identify conditions for this incoming buffer:
        // 1. Incoming buffer fits at the end of current container.
        // 2. Incoming buffer is already contained within stored samples.
        //    Nothing to do.
        // 3. Incoming buffer overlaps with stored samples at the end.
        // 4. Incoming buffer overlaps with stored samples at the begining.
        //    Note: this changes the lower sample and requires to extend
        //    the internal container from the begining.
        // 5. Incoming buffer doesn't overlap with current buffer. In order
        //    not to let gaps between samples, the internal container is
        //    cleared lower.
        // 6. The internal container is empty, import incoming buffer
        //    completely.
        let (lower_changed, incoming_lower, lower_to_add_rel, upper_to_add_rel) =
            if !self.samples.is_empty() {
                // not initializing
                if incoming_lower == self.upper {
                    // 1. append incoming buffer to the end of internal storage
                    #[cfg(test)]
                    trace!("case 1. appending to the end (full)");
                    // self.lower unchanged
                    self.upper = incoming_upper;
                    self.eos = false;
                    self.last_buffer_upper = incoming_upper;

                    (
                        false,             // lower_changed
                        incoming_lower,    // incoming_lower
                        0,                 // lower_to_add_rel
                        buffer_sample_len, // upper_to_add_rel
                    )
                } else if incoming_lower >= self.lower && incoming_upper <= self.upper {
                    // 2. incoming buffer included in current container
                    debug!(
                        concat!(
                            "case 2. contained in current container ",
                            "self [{}, {}], incoming [{}, {}]",
                        ),
                        self.lower,
                        self.upper,
                        incoming_lower,
                        incoming_upper
                    );
                    self.last_buffer_upper = incoming_upper;
                    (
                        false,          // lower_changed
                        incoming_lower, // incoming_lower
                        0,              // lower_to_add_rel
                        0,              // upper_to_add_rel
                    )
                } else if incoming_lower > self.lower && incoming_lower < self.upper {
                    // 3. can append [self.upper, upper] to the end
                    debug!(
                        "case 3. append to the end (partial) [{}, {}], incoming [{}, {}]",
                        self.upper, incoming_upper, incoming_lower, incoming_upper
                    );
                    // self.lower unchanged
                    let previous_upper = self.upper;
                    self.upper = incoming_upper;
                    self.eos = false;
                    // self.first_pts unchanged
                    self.last_buffer_upper = incoming_upper;
                    (
                        false,                           // lower_changed
                        incoming_lower,                  // incoming_lower
                        previous_upper - incoming_lower, // lower_to_add_rel
                        buffer_sample_len,               // upper_to_add_rel
                    )
                } else if incoming_upper < self.upper && incoming_upper >= self.lower {
                    // 4. can insert [lower, self.lower] at the begining
                    debug!(
                        "case 4. insert at the begining [{}, {}], incoming [{}, {}]",
                        incoming_lower, self.lower, incoming_lower, incoming_upper
                    );
                    let upper_to_add = self.lower;
                    self.lower = incoming_lower;
                    // self.upper unchanged
                    self.last_buffer_upper = incoming_upper;
                    (
                        true,                          // lower_changed
                        incoming_lower,                // incoming_lower
                        0,                             // lower_to_add_rel
                        upper_to_add - incoming_lower, // upper_to_add_rel
                    )
                } else {
                    // 5. can't merge with previous buffer
                    debug!(
                        "case 5. can't merge self [{}, {}], incoming [{}, {}]",
                        self.lower, self.upper, incoming_lower, incoming_upper
                    );
                    self.samples.clear();
                    self.lower = incoming_lower;
                    self.upper = incoming_upper;
                    self.eos = false;
                    self.last_buffer_upper = incoming_upper;
                    (
                        true,              // lower_changed
                        incoming_lower,    // incoming_lower
                        0,                 // lower_to_add_rel
                        buffer_sample_len, // upper_to_add_rel
                    )
                }
            } else {
                // 6. initializing
                debug!("init [{}, {}]", incoming_lower, incoming_upper);
                self.lower = incoming_lower;
                self.upper = incoming_upper;
                self.eos = false;
                self.last_buffer_upper = self.upper;
                (
                    true,              // lower_changed
                    incoming_lower,    // incoming_lower
                    0,                 // lower_to_add_rel
                    buffer_sample_len, // upper_to_add_rel
                )
            };

        // Don't drain if samples are to be added at the begining...
        // drain only if we have enough samples in history
        // TODO: it could be worth testing truncate instead
        // (this would require reversing the buffer alimentation
        // and iteration).
        // Don't drain samples if they might be used by the extractor
        // (limit known as argument lower_to_keep).
        if !lower_changed
            && self.samples.len() + (upper_to_add_rel - lower_to_add_rel) * self.channels
                > self.capacity
            && lower_to_keep.min(incoming_lower) > self.lower + self.drain_size / self.channels
        {
            debug!("draining... len before: {}", self.samples.len());
            self.samples.drain(..self.drain_size);
            self.lower += self.drain_size / self.channels;
        }

        if upper_to_add_rel > 0 {
            let map = buffer.map_readable().take().unwrap();
            let converter_iter = SampleConverterIter::new(
                map.as_slice(),
                self.audio_info.as_ref().unwrap(),
                lower_to_add_rel,
                upper_to_add_rel,
            ).unwrap();

            if !lower_changed || self.samples.is_empty() {
                for sample in converter_iter {
                    self.samples.push_back(sample);
                }
            } else {
                for sample in converter_iter.rev() {
                    self.samples.push_front(sample);
                }
            }
        }

        buffer_sample_len // nb of samples received
    }
// Add samples from the GStreamer pipeline to the AudioBuffer
// This buffer stores the complete set of samples in a time frame
// in order to be able to represent the audio at any given precision.
// Incoming samples are merged to the existing buffer when possible
// Returns: number of samples received
Add samples from the GStreamer pipeline to the AudioBuffer
This buffer stores the complete set of samples in a time frame
in order to be able to represent the audio at any given precision.
Incoming samples are merged to the existing buffer when possible
Returns: number of samples received
Add samples from the GStreamer pipeline to the AudioBuffer This buffer stores the complete set of samples in a time frame in order to be able to represent the audio at any given precision . Incoming samples are merged to the existing buffer when possible Returns : number of samples received
pub fn push_gst_buffer(&mut self, buffer: &gst::Buffer, lower_to_keep: usize) -> usize {
        if self.sample_duration == 0 {
            debug!("push_gst_buffer sample_duration is null");
            return 0;
        }
        let buffer_sample_len = buffer.get_size() / self.bytes_per_sample / self.channels;
        // Unfortunately, we can't rely on buffer_pts to figure out
        // the exact position in the segment. Some streams use a pts
        // value which is a rounded value to e.g ms and correct
        // the shift every n samples.
        // After an accurate seek, the buffer pts seems reliable,
        // however after a inaccurate seek, we get a rounded value.
        // The strategy here is to consider that each incoming buffer
        // in the same segment comes after last buffer (we might need
        // to check buffer drops for this) and in case of a new segment
        // we'll rely on the inaccurate pts value...
        if self.is_new_segment {
            self.segment_lower = (buffer.get_pts().unwrap() / self.sample_duration) as usize;
            self.last_buffer_upper = self.segment_lower;
            self.is_new_segment = false;
        }
        let incoming_lower = self.last_buffer_upper;
        let incoming_upper = incoming_lower + buffer_sample_len;
        // Identify conditions for this incoming buffer:
        // 1. Incoming buffer fits at the end of current container.
        // 2. Incoming buffer is already contained within stored samples.
        //    Nothing to do.
        // 3. Incoming buffer overlaps with stored samples at the end.
        // 4. Incoming buffer overlaps with stored samples at the begining.
        //    Note: this changes the lower sample and requires to extend
        //    the internal container from the begining.
        // 5. Incoming buffer doesn't overlap with current buffer. In order
        //    not to let gaps between samples, the internal container is
        //    cleared lower.
        // 6. The internal container is empty, import incoming buffer
        //    completely.
        let (lower_changed, incoming_lower, lower_to_add_rel, upper_to_add_rel) =
            if !self.samples.is_empty() {
                // not initializing
                if incoming_lower == self.upper {
                    // 1. append incoming buffer to the end of internal storage
                    #[cfg(test)]
                    trace!("case 1. appending to the end (full)");
                    // self.lower unchanged
                    self.upper = incoming_upper;
                    self.eos = false;
                    self.last_buffer_upper = incoming_upper;
                    (
                        false,             // lower_changed
                        incoming_lower,    // incoming_lower
                        0,                 // lower_to_add_rel
                        buffer_sample_len, // upper_to_add_rel
                    )
                } else if incoming_lower >= self.lower && incoming_upper <= self.upper {
                    // 2. incoming buffer included in current container
                    debug!(
                        concat!(
                            "case 2. contained in current container ",
                            "self [{}, {}], incoming [{}, {}]",
                        ),
                        self.lower,
                        self.upper,
                        incoming_lower,
                        incoming_upper
                    );
                    self.last_buffer_upper = incoming_upper;
                    (
                        false,          // lower_changed
                        incoming_lower, // incoming_lower
                        0,              // lower_to_add_rel
                        0,              // upper_to_add_rel
                    )
                } else if incoming_lower > self.lower && incoming_lower < self.upper {
                    // 3. can append [self.upper, upper] to the end
                    debug!(
                        "case 3. append to the end (partial) [{}, {}], incoming [{}, {}]",
                        self.upper, incoming_upper, incoming_lower, incoming_upper
                    );
                    // self.lower unchanged
                    let previous_upper = self.upper;
                    self.upper = incoming_upper;
                    self.eos = false;
                    // self.first_pts unchanged
                    self.last_buffer_upper = incoming_upper;
                    (
                        false,                           // lower_changed
                        incoming_lower,                  // incoming_lower
                        previous_upper - incoming_lower, // lower_to_add_rel
                        buffer_sample_len,               // upper_to_add_rel
                    )
                } else if incoming_upper < self.upper && incoming_upper >= self.lower {
                    // 4. can insert [lower, self.lower] at the begining
                    debug!(
                        "case 4. insert at the begining [{}, {}], incoming [{}, {}]",
                        incoming_lower, self.lower, incoming_lower, incoming_upper
                    );
                    let upper_to_add = self.lower;
                    self.lower = incoming_lower;
                    // self.upper unchanged
                    self.last_buffer_upper = incoming_upper;
                    (
                        true,                          // lower_changed
                        incoming_lower,                // incoming_lower
                        0,                             // lower_to_add_rel
                        upper_to_add - incoming_lower, // upper_to_add_rel
                    )
                } else {
                    // 5. can't merge with previous buffer
                    debug!(
                        "case 5. can't merge self [{}, {}], incoming [{}, {}]",
                        self.lower, self.upper, incoming_lower, incoming_upper
                    );
                    self.samples.clear();
                    self.lower = incoming_lower;
                    self.upper = incoming_upper;
                    self.eos = false;
                    self.last_buffer_upper = incoming_upper;
                    (
                        true,              // lower_changed
                        incoming_lower,    // incoming_lower
                        0,                 // lower_to_add_rel
                        buffer_sample_len, // upper_to_add_rel
                    )
                }
            } else {
                // 6. initializing
                debug!("init [{}, {}]", incoming_lower, incoming_upper);
                self.lower = incoming_lower;
                self.upper = incoming_upper;
                self.eos = false;
                self.last_buffer_upper = self.upper;
                (
                    true,              // lower_changed
                    incoming_lower,    // incoming_lower
                    0,                 // lower_to_add_rel
                    buffer_sample_len, // upper_to_add_rel
                )
            };
        // Don't drain if samples are to be added at the begining...
        // drain only if we have enough samples in history
        // TODO: it could be worth testing truncate instead
        // (this would require reversing the buffer alimentation
        // and iteration).
        // Don't drain samples if they might be used by the extractor
        // (limit known as argument lower_to_keep).
        if !lower_changed
            && self.samples.len() + (upper_to_add_rel - lower_to_add_rel) * self.channels
                > self.capacity
            && lower_to_keep.min(incoming_lower) > self.lower + self.drain_size / self.channels
        {
            debug!("draining... len before: {}", self.samples.len());
            self.samples.drain(..self.drain_size);
            self.lower += self.drain_size / self.channels;
        }
        if upper_to_add_rel > 0 {
            let map = buffer.map_readable().take().unwrap();
            let converter_iter = SampleConverterIter::new(
                map.as_slice(),
                self.audio_info.as_ref().unwrap(),
                lower_to_add_rel,
                upper_to_add_rel,
            ).unwrap();
            if !lower_changed || self.samples.is_empty() {
                for sample in converter_iter {
                    self.samples.push_back(sample);
                }
            } else {
                for sample in converter_iter.rev() {
                    self.samples.push_front(sample);
                }
            }
        }
        buffer_sample_len // nb of samples received
    }
pub fn push_gst_buffer ( & mut self , buffer : & gst :: Buffer , lower_to_keep : usize ) -> usize { if self . sample_duration == 0 { debug ! ( " " ) ; return 0 ; } let buffer_sample_len = buffer . get_size ( ) / self . bytes_per_sample / self . channels ; // Unfortunately, we can't rely on buffer_pts to figure out // the exact position in the segment. Some streams use a pts // value which is a rounded value to e.g ms and correct // the shift every n samples. // After an accurate seek, the buffer pts seems reliable, // however after a inaccurate seek, we get a rounded value. // The strategy here is to consider that each incoming buffer // in the same segment comes after last buffer (we might need // to check buffer drops for this) and in case of a new segment // we'll rely on the inaccurate pts value... if self . is_new_segment { self . segment_lower = ( buffer . get_pts ( ) . unwrap ( ) / self . sample_duration ) as usize ; self . last_buffer_upper = self . segment_lower ; self . is_new_segment = false ; } let incoming_lower = self . last_buffer_upper ; let incoming_upper = incoming_lower + buffer_sample_len ; // Identify conditions for this incoming buffer: // 1. Incoming buffer fits at the end of current container. // 2. Incoming buffer is already contained within stored samples. //    Nothing to do. // 3. Incoming buffer overlaps with stored samples at the end. // 4. Incoming buffer overlaps with stored samples at the begining. //    Note: this changes the lower sample and requires to extend //    the internal container from the begining. // 5. Incoming buffer doesn't overlap with current buffer. In order //    not to let gaps between samples, the internal container is //    cleared lower. // 6. The internal container is empty, import incoming buffer //    completely. let ( lower_changed , incoming_lower , lower_to_add_rel , upper_to_add_rel ) = if ! self . samples . is_empty ( ) { // not initializing if incoming_lower == self . upper { // 1. append incoming buffer to the end of internal storage # [ cfg ( test ) ] trace ! ( " " ) ; // self.lower unchanged self . upper = incoming_upper ; self . eos = false ; self . last_buffer_upper = incoming_upper ; ( false , // lower_changed incoming_lower , // incoming_lower 0 , // lower_to_add_rel buffer_sample_len , // upper_to_add_rel ) } else if incoming_lower >= self . lower && incoming_upper <= self . upper { // 2. incoming buffer included in current container debug ! ( concat ( " " " " ) self lower self upper incoming_lower incoming_upper ) ; self . last_buffer_upper = incoming_upper ; ( false , // lower_changed incoming_lower , // incoming_lower 0 , // lower_to_add_rel 0 , // upper_to_add_rel ) } else if incoming_lower > self . lower && incoming_lower < self . upper { // 3. can append [self.upper, upper] to the end debug ! ( " " self upper incoming_upper incoming_lower incoming_upper ) ; // self.lower unchanged let previous_upper = self . upper ; self . upper = incoming_upper ; self . eos = false ; // self.first_pts unchanged self . last_buffer_upper = incoming_upper ; ( false , // lower_changed incoming_lower , // incoming_lower previous_upper - incoming_lower , // lower_to_add_rel buffer_sample_len , // upper_to_add_rel ) } else if incoming_upper < self . upper && incoming_upper >= self . lower { // 4. can insert [lower, self.lower] at the begining debug ! ( " " incoming_lower self lower incoming_lower incoming_upper ) ; let upper_to_add = self . lower ; self . lower = incoming_lower ; // self.upper unchanged self . last_buffer_upper = incoming_upper ; ( true , // lower_changed incoming_lower , // incoming_lower 0 , // lower_to_add_rel upper_to_add - incoming_lower , // upper_to_add_rel ) } else { // 5. can't merge with previous buffer debug ! ( " " self lower self upper incoming_lower incoming_upper ) ; self . samples . clear ( ) ; self . lower = incoming_lower ; self . upper = incoming_upper ; self . eos = false ; self . last_buffer_upper = incoming_upper ; ( true , // lower_changed incoming_lower , // incoming_lower 0 , // lower_to_add_rel buffer_sample_len , // upper_to_add_rel ) } } else { // 6. initializing debug ! ( " " incoming_lower incoming_upper ) ; self . lower = incoming_lower ; self . upper = incoming_upper ; self . eos = false ; self . last_buffer_upper = self . upper ; ( true , // lower_changed incoming_lower , // incoming_lower 0 , // lower_to_add_rel buffer_sample_len , // upper_to_add_rel ) } ; // Don't drain if samples are to be added at the begining... // drain only if we have enough samples in history // TODO: it could be worth testing truncate instead // (this would require reversing the buffer alimentation // and iteration). // Don't drain samples if they might be used by the extractor // (limit known as argument lower_to_keep). if ! lower_changed && self . samples . len ( ) + ( upper_to_add_rel - lower_to_add_rel ) * self . channels > self . capacity && lower_to_keep . min ( incoming_lower ) > self . lower + self . drain_size / self . channels { debug ! ( " " self samples len ( ) ) ; self . samples . drain ( .. self . drain_size ) ; self . lower += self . drain_size / self . channels ; } if upper_to_add_rel > 0 { let map = buffer . map_readable ( ) . take ( ) . unwrap ( ) ; let converter_iter = SampleConverterIter :: new ( map . as_slice ( ) , self . audio_info . as_ref ( ) . unwrap ( ) , lower_to_add_rel , upper_to_add_rel , ) . unwrap ( ) ; if ! lower_changed || self . samples . is_empty ( ) { for sample in converter_iter { self . samples . push_back ( sample ) ; } } else { for sample in converter_iter . rev ( ) { self . samples . push_front ( sample ) ; } } } buffer_sample_len // nb of samples received }
Add samples from the GStreamer pipeline to the AudioBuffer
This buffer stores the complete set of samples in a time frame
in order to be able to represent the audio at any given precision.
Add samples from the GStreamer pipeline to the AudioBuffer This buffer stores the complete set of samples in a time frame in order to be able to represent the audio at any given precision .
&mut self
buffer
&gst::Buffer
lower_to_keep
usize
&mut self
buffer
&gst::Buffer
lower_to_keep
usize