| 602 | } |
| 603 | |
| 604 | static bool |
| 605 | FfmpegScanStream(AVFormatContext &format_context, TagHandler &handler) |
| 606 | { |
| 607 | const int find_result = |
| 608 | avformat_find_stream_info(&format_context, nullptr); |
| 609 | if (find_result < 0) |
| 610 | return false; |
| 611 | |
| 612 | const int audio_stream = ffmpeg_find_audio_stream(format_context); |
| 613 | if (audio_stream < 0) |
| 614 | return false; |
| 615 | |
| 616 | const AVStream &stream = *format_context.streams[audio_stream]; |
| 617 | if (stream.duration != (int64_t)AV_NOPTS_VALUE) |
| 618 | handler.OnDuration(FromFfmpegTime(stream.duration, |
| 619 | stream.time_base)); |
| 620 | else if (format_context.duration != (int64_t)AV_NOPTS_VALUE) |
| 621 | handler.OnDuration(FromFfmpegTime(format_context.duration, |
| 622 | AV_TIME_BASE_Q)); |
| 623 | |
| 624 | const auto &codec_params = *stream.codecpar; |
| 625 | |
| 626 | #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 25, 100) |
| 627 | const unsigned channels = codec_params.ch_layout.nb_channels; |
| 628 | #else |
| 629 | const unsigned channels = codec_params.channels; |
| 630 | #endif |
| 631 | |
| 632 | try { |
| 633 | handler.OnAudioFormat(CheckAudioFormat(codec_params.sample_rate, |
| 634 | ffmpeg_sample_format(AVSampleFormat(codec_params.format)), |
| 635 | channels)); |
| 636 | } catch (...) { |
| 637 | } |
| 638 | |
| 639 | FfmpegScanMetadata(format_context, audio_stream, handler); |
| 640 | |
| 641 | if (handler.WantPicture()) { |
| 642 | const auto *picture_stream = FindPictureStream(format_context); |
| 643 | if (picture_stream != nullptr) |
| 644 | handler.OnPicture(GetMimeType(*picture_stream), |
| 645 | ToSpan(picture_stream->attached_pic)); |
| 646 | } |
| 647 | |
| 648 | return true; |
| 649 | } |
| 650 | |
| 651 | static bool |
| 652 | ffmpeg_scan_stream(InputStream &is, TagHandler &handler) |
no test coverage detected