1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
#pragma once
#include <atomic>
#include "defs.h"
#include "time_keeper.h"
namespace ffmpeg {
/**
* Class uses FFMPEG library to decode one media stream (audio or video).
*/
class Stream {
public:
Stream(
AVFormatContext* inputCtx,
MediaFormat format,
bool convertPtsToWallTime,
int64_t loggingUuid);
virtual ~Stream();
// returns 0 - on success or negative error
// num_threads sets up the codec context for multithreading if needed
// default is set to single thread in order to not break BC
int openCodec(std::vector<DecoderMetadata>* metadata, int num_threads = 1);
// returns 1 - if packet got consumed, 0 - if it's not, and < 0 on error
int decodePacket(
const AVPacket* packet,
DecoderOutputMessage* out,
bool headerOnly,
bool* hasMsg);
// returns stream index
int getIndex() const {
return format_.stream;
}
// returns 1 - if message got a payload, 0 - if it's not, and < 0 on error
int flush(DecoderOutputMessage* out, bool headerOnly);
// return media format
MediaFormat getMediaFormat() const {
return format_;
}
protected:
virtual int initFormat() = 0;
// returns number processed bytes from packet, or negative error
virtual int analyzePacket(const AVPacket* packet, bool* gotFrame);
// returns number processed bytes from packet, or negative error
virtual int copyFrameBytes(ByteStorage* out, bool flush) = 0;
// sets output format
virtual void setHeader(DecoderHeader* header, bool flush);
// set frame pts
virtual void setFramePts(DecoderHeader* header, bool flush);
// finds codec
virtual AVCodec* findCodec(AVCodecParameters* params);
private:
// returns 1 - if message got a payload, 0 - if it's not, and < 0 on error
int getMessage(DecoderOutputMessage* out, bool flush, bool headerOnly);
protected:
AVFormatContext* const inputCtx_;
MediaFormat format_;
const bool convertPtsToWallTime_;
int64_t loggingUuid_;
AVCodecContext* codecCtx_{nullptr};
AVFrame* frame_{nullptr};
std::atomic<size_t> numGenerator_{0};
TimeKeeper keeper_;
// estimated next frame pts for flushing the last frame
int64_t nextPts_{0};
double fps_{30.};
// this is a dumb conservative limit; ideally we'd use
// int max_threads = at::get_num_threads(); but this would cause
// fb sync to fail as it would add dependency to ATen to the decoder API
const int max_threads = 12;
};
} // namespace ffmpeg
|