#include "Codec.h" #include "ffcpp.h" #include namespace ffcpp { Codec::Codec(): _codecCtx(nullptr), _codec(nullptr) { } Codec::Codec(AVCodecContext *ctx, CodecType type): _codecCtx(ctx) { if(type == CodecType::Encoder) { _codec = avcodec_find_encoder(ctx->codec_id); } else { _codec = avcodec_find_decoder(ctx->codec_id); } if(!_codec) throw std::runtime_error("cannot find codec"); int res = avcodec_open2(_codecCtx, _codec, nullptr); throwIfError(res, "cannot open codec"); } Codec::Codec(AVCodecContext *ctx, AVCodec *codec) { _codecCtx = ctx; _codec = codec; int res = avcodec_open2(_codecCtx, _codec, nullptr); throwIfError(res, "cannot open codec"); } Codec::~Codec() { if(_codecCtx) { avcodec_close(_codecCtx); } } Codec::operator AVCodecContext*() const { return _codecCtx; } int Codec::width() const { return _codecCtx->width; } int Codec::height() const { return _codecCtx->height; } AVRational Codec::timeBase() const { return _codecCtx->time_base; } int Codec::capabilities() const { return _codec->capabilities; } AVPixelFormat Codec::pixelFormat() const { return _codecCtx->pix_fmt; } AVSampleFormat Codec::sampleFormat() const { return _codecCtx->codec->sample_fmts[0]; } int Codec::frameSize() const { return _codecCtx->frame_size; } int Codec::channels() const { return _codecCtx->channels; } int Codec::sampleRate() const { return _codecCtx->sample_rate; } void Codec::setWidth(int width) { _codecCtx->width = width; } void Codec::setHeight(int height) { _codecCtx->height = height; } void Codec::setPixelFormat(AVPixelFormat pixelFormat) { _codecCtx->pix_fmt = pixelFormat; } Codec::Codec(Codec&& c) noexcept { *this = std::move(c); } Codec& Codec::operator=(Codec&& c) noexcept { _codec = c._codec; _codecCtx = c._codecCtx; c._codec = nullptr; c._codecCtx = nullptr; return *this; } Frame Codec::decode(Packet &packet) { Frame frame; int gotPicture = 0; auto decFunc = (_codecCtx->codec_type == AVMEDIA_TYPE_VIDEO ? avcodec_decode_video2 : avcodec_decode_audio4); while(!gotPicture) { int res = decFunc(_codecCtx, frame, &gotPicture, packet); if(res < 0) throw std::runtime_error("cannot decode packet"); } if(_codecCtx->codec_type == AVMEDIA_TYPE_VIDEO) { frame.guessPts(); } return frame; } Packet Codec::encode(AVFrame* frame) { Packet packet; int gotPacket = 0; auto encFunc = (_codecCtx->codec_type == AVMEDIA_TYPE_VIDEO ? avcodec_encode_video2 : avcodec_encode_audio2); int res = encFunc(_codecCtx, packet, frame, &gotPacket); if(res < 0) throw std::runtime_error("cannot encode frame"); return packet; } Frame Codec::createAudioFrame() const { return Frame(_codecCtx->frame_size, _codecCtx->channels, _codecCtx->codec->sample_fmts[0], _codecCtx->sample_rate); } }