LCOV - code coverage report
Current view: top level - src/media - media_decoder.h (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 85.7 % 21 18
Test Date: 2026-06-13 09:18:46 Functions: 75.0 % 12 9

            Line data    Source code
       1              : /*
       2              :  *  Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3              :  *
       4              :  *  This program is free software: you can redistribute it and/or modify
       5              :  *  it under the terms of the GNU General Public License as published by
       6              :  *  the Free Software Foundation, either version 3 of the License, or
       7              :  *  (at your option) any later version.
       8              :  *
       9              :  *  This program is distributed in the hope that it will be useful,
      10              :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12              :  *  GNU General Public License for more details.
      13              :  *
      14              :  *  You should have received a copy of the GNU General Public License
      15              :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16              :  */
      17              : #pragma once
      18              : 
      19              : #ifdef HAVE_CONFIG_H
      20              : #include "config.h"
      21              : #endif
      22              : 
      23              : #include "rational.h"
      24              : 
      25              : #ifdef ENABLE_VIDEO
      26              : #include "video/video_base.h"
      27              : #endif // ENABLE_VIDEO
      28              : 
      29              : #ifdef ENABLE_HWACCEL
      30              : #include "video/accel.h"
      31              : #endif
      32              : #include "logger.h"
      33              : 
      34              : #include "media_device.h"
      35              : #include "media_stream.h"
      36              : #include "media_buffer.h"
      37              : #include "noncopyable.h"
      38              : 
      39              : #include <asio/steady_timer.hpp>
      40              : 
      41              : #include <string>
      42              : #include <memory>
      43              : #include <queue>
      44              : 
      45              : extern "C" {
      46              : struct AVCodecContext;
      47              : struct AVStream;
      48              : struct AVDictionary;
      49              : struct AVFormatContext;
      50              : struct AVCodec;
      51              : enum AVMediaType;
      52              : }
      53              : 
      54              : namespace libjami {
      55              : class AudioFrame;
      56              : }
      57              : 
      58              : namespace jami {
      59              : 
      60              : using AudioFrame = libjami::AudioFrame;
      61              : #ifdef ENABLE_VIDEO
      62              : using VideoFrame = libjami::VideoFrame;
      63              : #endif
      64              : struct AudioFormat;
      65              : class RingBuffer;
      66              : class Resampler;
      67              : class MediaIOHandle;
      68              : class MediaDecoder;
      69              : 
      70              : enum class DecodeStatus : uint8_t {
      71              :     Success,
      72              :     FrameFinished,
      73              :     EndOfFile,
      74              :     ReadError,
      75              :     DecodeError,
      76              :     RestartRequired,
      77              :     FallBack
      78              : };
      79              : 
      80              : class MediaDemuxer : public std::enable_shared_from_this<MediaDemuxer>
      81              : {
      82              : public:
      83              :     MediaDemuxer();
      84              :     ~MediaDemuxer();
      85              : 
      86              :     enum class Status : uint8_t { Success, EndOfFile, ReadBufferOverflow, ReadError, FallBack, RestartRequired };
      87              : 
      88              :     static const char* getStatusStr(Status status);
      89              : 
      90              :     enum class CurrentState : uint8_t { Demuxing, Finished };
      91              :     using StreamCallback = std::function<DecodeStatus(AVPacket&)>;
      92              : 
      93              :     int openInput(const DeviceParams&);
      94              : 
      95              :     void setInterruptCallback(int (*cb)(void*), void* opaque);
      96              :     void setIOContext(MediaIOHandle* ioctx);
      97              : 
      98              :     void setKeyFrameRequestCb(std::function<void()> cb);
      99              : 
     100              :     void findStreamInfo(bool videoStream = false);
     101              :     int selectStream(AVMediaType type);
     102              : 
     103          323 :     void setStreamCallback(unsigned stream, StreamCallback cb = {})
     104              :     {
     105          323 :         if (streams_.size() <= stream)
     106          319 :             streams_.resize(stream + 1);
     107          323 :         streams_[stream] = std::move(cb);
     108          323 :     }
     109              : 
     110           15 :     void updateCurrentState(MediaDemuxer::CurrentState state) { currentState_ = state; }
     111              : 
     112              :     void setFileFinishedCb(std::function<void(bool)> cb);
     113              : 
     114              :     MediaDemuxer::CurrentState getCurrentState() { return currentState_; }
     115              : 
     116          323 :     AVStream* getStream(unsigned stream)
     117              :     {
     118          323 :         if (stream >= inputCtx_->nb_streams) {
     119            0 :             JAMI_ERROR("Stream index is out of range: {}", stream);
     120            0 :             return {};
     121              :         }
     122          323 :         return inputCtx_->streams[stream];
     123              :     }
     124              : 
     125              :     Status decode();
     126              :     Status demuxe();
     127              : 
     128              :     int64_t getDuration() const;
     129              :     bool seekFrame(int stream_index, int64_t timestamp);
     130              :     void setNeedFrameCb(std::function<void()> cb);
     131              :     bool emitFrame(bool isAudio);
     132              : 
     133              : private:
     134              :     bool streamInfoFound_ {false};
     135              :     std::unique_ptr<asio::steady_timer> streamInfoTimer_;
     136              :     AVFormatContext* inputCtx_ = nullptr;
     137              :     std::vector<StreamCallback> streams_;
     138              :     int64_t startTime_;
     139              :     int64_t lastReadPacketTime_ {};
     140              :     DeviceParams inputParams_;
     141              :     AVDictionary* options_ = nullptr;
     142              :     MediaDemuxer::CurrentState currentState_;
     143              :     std::mutex inputCtxMutex_ {};
     144              :     std::mutex audioBufferMutex_ {};
     145              :     std::mutex videoBufferMutex_ {};
     146              :     std::queue<std::unique_ptr<AVPacket, std::function<void(AVPacket*)>>> videoBuffer_ {};
     147              :     std::queue<std::unique_ptr<AVPacket, std::function<void(AVPacket*)>>> audioBuffer_ {};
     148              :     std::function<void()> needFrameCb_;
     149              :     std::function<void(bool)> fileFinishedCb_;
     150              :     std::function<void()> keyFrameRequestCb_;
     151              :     void clearFrames();
     152              :     bool pushFrameFrom(std::queue<std::unique_ptr<AVPacket, std::function<void(AVPacket*)>>>& buffer,
     153              :                        bool isAudio,
     154              :                        std::mutex& mutex);
     155              :     int baseWidth_ {};
     156              :     int baseHeight_ {};
     157              : };
     158              : 
     159              : class MediaDecoder
     160              : {
     161              : public:
     162              :     MediaDecoder();
     163              :     MediaDecoder(MediaObserver observer);
     164              :     MediaDecoder(const std::shared_ptr<MediaDemuxer>& demuxer, int index);
     165              :     MediaDecoder(const std::shared_ptr<MediaDemuxer>& demuxer, int index, MediaObserver observer);
     166              :     MediaDecoder(const std::shared_ptr<MediaDemuxer>& demuxer, AVMediaType type)
     167              :         : MediaDecoder(demuxer, demuxer->selectStream(type))
     168              :     {}
     169              :     ~MediaDecoder();
     170              : 
     171           10 :     void emulateRate() { emulateRate_ = true; }
     172              : 
     173              :     int openInput(const DeviceParams&);
     174              :     void setInterruptCallback(int (*cb)(void*), void* opaque);
     175              :     void setIOContext(MediaIOHandle* ioctx);
     176              : 
     177              :     int setup(AVMediaType type);
     178          177 :     int setupAudio() { return setup(AVMEDIA_TYPE_AUDIO); }
     179          136 :     int setupVideo() { return setup(AVMEDIA_TYPE_VIDEO); }
     180              :     void setKeyFrameRequestCb(std::function<void()> cb);
     181              : 
     182              :     MediaDemuxer::Status decode();
     183              :     DecodeStatus flush();
     184              : 
     185              :     int getWidth() const;
     186              :     int getHeight() const;
     187              :     std::string getDecoderName() const;
     188              : 
     189              :     rational<double> getFps() const;
     190              :     AVPixelFormat getPixelFormat() const;
     191              : 
     192              :     void updateStartTime(int64_t startTime);
     193              : 
     194              :     bool emitFrame(bool isAudio);
     195              :     void flushBuffers();
     196              :     void setSeekTime(int64_t time);
     197              : #ifdef ENABLE_HWACCEL
     198              :     void enableAccel(bool enableAccel);
     199              : #endif
     200              : 
     201              :     MediaStream getStream(const std::string& name = "") const;
     202              : 
     203          136 :     void setResolutionChangedCallback(std::function<void(int, int)> cb) { resolutionChangedCallback_ = std::move(cb); }
     204              : 
     205          175 :     void setFEC(bool enable) { fecEnabled_ = enable; }
     206              : 
     207          314 :     void setContextCallback(const std::function<void()>& cb)
     208              :     {
     209          314 :         firstDecode_.exchange(true);
     210          314 :         contextCallback_ = cb;
     211          314 :     }
     212              : 
     213              : private:
     214              :     NON_COPYABLE(MediaDecoder);
     215              : 
     216              :     DecodeStatus decode(AVPacket&);
     217              : 
     218              :     rational<unsigned> getTimeBase() const;
     219              : 
     220              :     std::shared_ptr<MediaDemuxer> demuxer_;
     221              : 
     222              :     const AVCodec* inputDecoder_ = nullptr;
     223              :     AVCodecContext* decoderCtx_ = nullptr;
     224              :     AVStream* avStream_ = nullptr;
     225              :     bool emulateRate_ = false;
     226              :     bool passthrough_ = false;
     227              :     int64_t startTime_;
     228              :     int64_t lastTimestamp_ {0};
     229              : 
     230              :     DeviceParams inputParams_;
     231              : 
     232              :     int correctPixFmt(int input_pix_fmt);
     233              :     int setupStream();
     234              : 
     235              :     bool fallback_ = false;
     236              : 
     237              : #ifdef ENABLE_HWACCEL
     238              :     bool enableAccel_ = true;
     239              :     std::unique_ptr<video::HardwareAccel> accel_;
     240              :     unsigned short accelFailures_ = 0;
     241              : #endif
     242              :     MediaObserver callback_;
     243              :     int prepareDecoderContext();
     244              :     int64_t seekTime_ = -1;
     245            0 :     void resetSeekTime() { seekTime_ = -1; }
     246              :     std::function<void(int, int)> resolutionChangedCallback_;
     247              : 
     248              :     int width_;
     249              :     int height_;
     250              : 
     251              :     bool fecEnabled_ {false};
     252              : 
     253              :     std::function<void()> contextCallback_;
     254              :     std::atomic_bool firstDecode_ {true};
     255              : 
     256              : protected:
     257              :     AVDictionary* options_ = nullptr;
     258              : };
     259              : 
     260              : } // namespace jami
        

Generated by: LCOV version 2.0-1