ffconv/ffcpp/Codec.cpp

112 lines
2.3 KiB
C++

#include "Codec.h"
#include "ffcpp.h"
#include <stdexcept>
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;
}
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) {
*this = std::move(c);
}
Codec& Codec::operator=(Codec&& c) {
_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");
}
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;
}
}