static inline int get_frame_length ( libavsmash_audio_decode_handler_t *adhp, uint32_t frame_number, uint32_t *frame_length, libavsmash_summary_t **sp ) { lsmash_sample_t sample; if( lsmash_get_sample_info_from_media_timeline( adhp->root, adhp->track_ID, frame_number, &sample ) ) return -1; *sp = &adhp->config.entries[ sample.index - 1 ]; libavsmash_summary_t *s = *sp; if( s->extended.frame_length == 0 ) { /* variable frame length * Guess the frame length from sample duration. */ if( lsmash_get_sample_delta_from_media_timeline( adhp->root, adhp->track_ID, frame_number, frame_length ) ) return -1; *frame_length *= s->extended.upsampling; } else /* constant frame length */ *frame_length = s->extended.frame_length; return 0; }
int libavsmash_video_get_sample_duration ( libavsmash_video_decode_handler_t *vdhp, uint32_t coded_sample_number, uint32_t *sample_duration ) { return lsmash_get_sample_delta_from_media_timeline( vdhp->root, vdhp->track_id, coded_sample_number, sample_duration ); }
uint64_t libavsmash_count_overall_pcm_samples ( libavsmash_audio_decode_handler_t *adhp, int output_sample_rate, uint64_t *skip_decoded_samples /* converted to upsampled in this function */ ) { codec_configuration_t *config = &adhp->config; extended_summary_t *es = NULL; /* Here, the decoder upsampling is defined only when libavcodec doesn't return upsampled length as AVCodecContext.frame_size. */ int current_sample_rate = 0; /* after the decoder upsampling */ uint32_t current_index = 0; uint32_t current_frame_length = 0; /* before the decoder upsampling */ uint64_t sequence_pcm_count = 0; /* before the decoder upsampling */ uint64_t prior_sequences_pcm_count = 0; /* before the decoder upsampling */ uint64_t overall_pcm_count = 0; /* after the decoder and the resampler upsampling */ uint64_t orig_skip_decoded_samples = *skip_decoded_samples; /* before the decoder upsampling */ /* Count the number of output PCM audio samples in each sequence. */ *skip_decoded_samples = 0; for( uint32_t i = 1; i <= adhp->frame_count; i++ ) { /* Get configuration index. */ lsmash_sample_t sample; if( lsmash_get_sample_info_from_media_timeline( adhp->root, adhp->track_ID, i, &sample ) ) continue; if( current_index != sample.index ) { es = &config->entries[ sample.index - 1 ].extended; current_index = sample.index; } else if( !es ) continue; /* Get audio frame length. */ uint32_t frame_length; if( es->frame_length ) frame_length = es->frame_length; else if( lsmash_get_sample_delta_from_media_timeline( adhp->root, adhp->track_ID, i, &frame_length ) ) continue; /* */ if( (current_sample_rate != es->sample_rate && es->sample_rate > 0) || current_frame_length != frame_length ) { /* Encountered a new sequence. */ if( current_sample_rate > 0 ) { /* Add the number of decoded PCM audio samples which shall be skipped. */ if( orig_skip_decoded_samples > prior_sequences_pcm_count ) { if( orig_skip_decoded_samples >= prior_sequences_pcm_count + sequence_pcm_count ) /* All decoded PCM audio samples in the previous sequence shall be skipped. */ *skip_decoded_samples += sequence_pcm_count * es->upsampling; else /* 0 < orig_skip_decoded_samples - prior_sequences_pcm_count < sequence_pcm_count * Partial decoded PCM audio samples in the previous sequence are not skipped. */ *skip_decoded_samples += (orig_skip_decoded_samples - prior_sequences_pcm_count) * es->upsampling; } prior_sequences_pcm_count += sequence_pcm_count; /* Add the number of output PCM audio samples in the previous sequence. */ overall_pcm_count += count_sequence_output_pcm_samples( sequence_pcm_count * es->upsampling, *skip_decoded_samples, current_sample_rate, output_sample_rate ); sequence_pcm_count = 0; } current_sample_rate = es->sample_rate > 0 ? es->sample_rate : config->ctx->sample_rate; current_frame_length = frame_length; } sequence_pcm_count += frame_length; } if( !es || (sequence_pcm_count == 0 && overall_pcm_count == 0) ) return 0; /* Count the number of output PCM audio samples in the last sequence. */ if( orig_skip_decoded_samples > prior_sequences_pcm_count ) *skip_decoded_samples += (orig_skip_decoded_samples - prior_sequences_pcm_count) * es->upsampling; current_sample_rate = es->sample_rate > 0 ? es->sample_rate : config->ctx->sample_rate; overall_pcm_count += count_sequence_output_pcm_samples( sequence_pcm_count * es->upsampling, *skip_decoded_samples, current_sample_rate, output_sample_rate ); /* Return the number of output PCM audio samples. */ return overall_pcm_count; }