- return av_get_bytes_per_sample (audio_sample_format ());
-}
-
-int
-FFmpegDecoder::minimal_run (boost::function<bool (optional<ContentTime>, optional<ContentTime>, int)> finished)
-{
- int frames_read = 0;
- optional<ContentTime> last_video;
- optional<ContentTime> last_audio;
-
- while (!finished (last_video, last_audio, frames_read)) {
- int r = av_read_frame (_format_context, &_packet);
- if (r < 0) {
- /* We should flush our decoders here, possibly yielding a few more frames,
- but the consequence of having to do that is too hideous to contemplate.
- Instead we give up and say that you can't seek too close to the end
- of a file.
- */
- return frames_read;
- }
-
- ++frames_read;
-
- double const time_base = av_q2d (_format_context->streams[_packet.stream_index]->time_base);
-
- if (_packet.stream_index == _video_stream) {
-
- avcodec_get_frame_defaults (_frame);
-
- int got_picture = 0;
- r = avcodec_decode_video2 (video_codec_context(), _frame, &got_picture, &_packet);
- if (r >= 0 && got_picture) {
- last_video = ContentTime::from_seconds (av_frame_get_best_effort_timestamp (_frame) * time_base) + _pts_offset;
- }
-
- } else if (_ffmpeg_content->audio_stream() && _ffmpeg_content->audio_stream()->uses_index (_format_context, _packet.stream_index)) {
- AVPacket copy_packet = _packet;
- while (copy_packet.size > 0) {
-
- int got_frame;
- r = avcodec_decode_audio4 (audio_codec_context(), _frame, &got_frame, &_packet);
- if (r >= 0 && got_frame) {
- last_audio = ContentTime::from_seconds (av_frame_get_best_effort_timestamp (_frame) * time_base) + _pts_offset;
- }
-
- copy_packet.data += r;
- copy_packet.size -= r;
- }
- }
-
- av_free_packet (&_packet);
- }
-
- return frames_read;
-}
-
-bool
-FFmpegDecoder::seek_overrun_finished (ContentTime seek, optional<ContentTime> last_video, optional<ContentTime> last_audio) const
-{
- return (last_video && last_video.get() >= seek) || (last_audio && last_audio.get() >= seek);
-}
-
-bool
-FFmpegDecoder::seek_final_finished (int n, int done) const
-{
- return n == done;
-}
-
-void
-FFmpegDecoder::seek_and_flush (ContentTime t)
-{
- ContentTime const u = t - _pts_offset;
- int64_t s = u.seconds() / av_q2d (_format_context->streams[_video_stream]->time_base);
-
- if (_ffmpeg_content->audio_stream ()) {
- s = min (
- s, int64_t (u.seconds() / av_q2d (_ffmpeg_content->audio_stream()->stream(_format_context)->time_base))
- );
- }
-
- /* Ridiculous empirical hack */
- s--;
- if (s < 0) {
- s = 0;
- }
-
- av_seek_frame (_format_context, _video_stream, s, 0);
-
- avcodec_flush_buffers (video_codec_context());
- if (audio_codec_context ()) {
- avcodec_flush_buffers (audio_codec_context ());
- }
- if (_subtitle_codec_context) {
- avcodec_flush_buffers (_subtitle_codec_context);
- }