diff options
| author | Carl Hetherington <cth@carlh.net> | 2024-10-19 21:29:54 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2024-11-01 01:40:30 +0100 |
| commit | 738ced15ead0f029cf2becf9b77d7adf37e733e3 (patch) | |
| tree | 535e41340b94a21429f6b82c3588d51d5ceec1b8 /src/lib | |
| parent | 24cfca51dffed98f0b115ca36f9a8478753e2432 (diff) | |
Obtain audio length by scanning through the file if required (#2880).
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/audio_stream.h | 5 | ||||
| -rw-r--r-- | src/lib/ffmpeg_examiner.cc | 57 | ||||
| -rw-r--r-- | src/lib/ffmpeg_examiner.h | 1 |
3 files changed, 46 insertions, 17 deletions
diff --git a/src/lib/audio_stream.h b/src/lib/audio_stream.h index cf874242f..b125eb8c0 100644 --- a/src/lib/audio_stream.h +++ b/src/lib/audio_stream.h @@ -54,6 +54,11 @@ public: return _length; } + void set_length(Frame length) { + boost::mutex::scoped_lock lm (_mutex); + _length = length; + } + int channels () const; boost::optional<int> bit_depth() const; diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index 31f1a3d64..810a6eba2 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -78,7 +78,10 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Jo s->codecpar->channel_layout = av_get_default_channel_layout (s->codecpar->channels); } - DCPOMATIC_ASSERT (_format_context->duration != AV_NOPTS_VALUE); + if (_format_context->duration == AV_NOPTS_VALUE) { + _need_audio_length = true; + } + DCPOMATIC_ASSERT (codec->name); _audio_streams.push_back ( @@ -87,7 +90,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Jo codec->name, s->id, s->codecpar->sample_rate, - llrint ((double(_format_context->duration) / AV_TIME_BASE) * s->codecpar->sample_rate), + _need_audio_length ? 0 : rint ((double(_format_context->duration) / AV_TIME_BASE) * s->codecpar->sample_rate), s->codecpar->channels, s->codecpar->bits_per_raw_sample ? s->codecpar->bits_per_raw_sample : s->codecpar->bits_per_coded_sample ) @@ -114,6 +117,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Jo * - the first video. * - the first audio for each stream. * - the top-field-first and repeat-first-frame values ("temporal_reference") for the first PULLDOWN_CHECK_FRAMES video frames. + * or forever if _need_length is true. */ int64_t const len = _file_group.length (); @@ -122,6 +126,8 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Jo * and a string seems a reasonably neat way to do that. */ string temporal_reference; + bool carry_on_video = false; + std::vector<bool> carry_on_audio(_audio_streams.size()); while (true) { auto packet = av_packet_alloc (); DCPOMATIC_ASSERT (packet); @@ -141,27 +147,37 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Jo auto context = _codec_context[packet->stream_index]; - auto carry_on = false; - - if (_video_stream && packet->stream_index == _video_stream.get()) { - if (video_packet(context, temporal_reference, packet)) { - carry_on = true; + boost::optional<size_t> audio_stream_index; + for (size_t i = 0; i < _audio_streams.size(); ++i) { + if (_audio_streams[i]->uses_index(_format_context, packet->stream_index)) { + audio_stream_index = i; } } - for (size_t i = 0; i < _audio_streams.size(); ++i) { - if (_audio_streams[i]->uses_index(_format_context, packet->stream_index)) { - if (audio_packet(context, _audio_streams[i], packet)) { - carry_on = true; - } + bool const video = _video_stream && packet->stream_index == *_video_stream; + + if (!video && !audio_stream_index) { + av_packet_free(&packet); + continue; + } + + if (video) { + carry_on_video = video_packet(context, temporal_reference, packet); + } + + if (audio_stream_index) { + if (audio_packet(context, _audio_streams[*audio_stream_index], packet)) { + carry_on_audio[*audio_stream_index] = true; } } av_packet_free (&packet); - if (!carry_on) { - /* All done */ - break; + if (!carry_on_video) { + if (std::find(carry_on_audio.begin(), carry_on_audio.end(), true) == carry_on_audio.end()) { + /* All done */ + break; + } } } @@ -262,7 +278,7 @@ FFmpegExaminer::video_packet (AVCodecContext* context, string& temporal_referenc bool FFmpegExaminer::audio_packet (AVCodecContext* context, shared_ptr<FFmpegAudioStream> stream, AVPacket* packet) { - if (stream->first_audio) { + if (stream->first_audio && !_need_audio_length) { return false; } @@ -278,7 +294,14 @@ FFmpegExaminer::audio_packet (AVCodecContext* context, shared_ptr<FFmpegAudioStr return false; } - stream->first_audio = frame_time (frame, stream->stream(_format_context)); + if (!stream->first_audio) { + stream->first_audio = frame_time(frame, stream->stream(_format_context)); + } + + if (_need_audio_length) { + stream->set_length(frame_time(frame, stream->stream(_format_context)).get_value_or({}).frames_round(stream->frame_rate()) + frame->nb_samples); + } + return true; } diff --git a/src/lib/ffmpeg_examiner.h b/src/lib/ffmpeg_examiner.h index f6fe8c423..57c97c542 100644 --- a/src/lib/ffmpeg_examiner.h +++ b/src/lib/ffmpeg_examiner.h @@ -103,6 +103,7 @@ private: */ Frame _video_length = 0; bool _need_video_length = false; + bool _need_audio_length = false; boost::optional<double> _rotation; bool _pulldown = false; |
