added some C++ wrappers
This commit is contained in:
parent
db9d3c39a1
commit
d7f8c733ec
@ -11,6 +11,6 @@ link_directories(${FFMPEG_LIBRARY_DIRS})
|
|||||||
|
|
||||||
#message(FATAL_ERROR ${FFMPEG_LIBRARIES})
|
#message(FATAL_ERROR ${FFMPEG_LIBRARIES})
|
||||||
|
|
||||||
set(SOURCE_FILES main.cpp)
|
set(SOURCE_FILES main.cpp ffcpp/MediaFile.cpp ffcpp/MediaFile.h ffcpp/ffcpp.cpp ffcpp/ffcpp.h ffcpp/Stream.cpp ffcpp/Stream.h ffcpp/Codec.cpp ffcpp/Codec.h)
|
||||||
add_executable(ffConv ${SOURCE_FILES})
|
add_executable(ffConv ${SOURCE_FILES})
|
||||||
target_link_libraries(ffConv ${FFMPEG_LIBRARIES})
|
target_link_libraries(ffConv ${FFMPEG_LIBRARIES})
|
||||||
72
ffcpp/Codec.cpp
Normal file
72
ffcpp/Codec.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#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() {
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
ffcpp/Codec.h
Normal file
41
ffcpp/Codec.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef FFCONV_CODEC_H
|
||||||
|
#define FFCONV_CODEC_H
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ffcpp {
|
||||||
|
|
||||||
|
enum class CodecType {
|
||||||
|
Encoder,
|
||||||
|
Decoder
|
||||||
|
};
|
||||||
|
|
||||||
|
class Codec {
|
||||||
|
private:
|
||||||
|
AVCodecContext* _codecCtx;
|
||||||
|
AVCodec* _codec;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Codec();
|
||||||
|
Codec(AVCodecContext* ctx, CodecType type);
|
||||||
|
Codec(AVCodecContext* ctx, AVCodec* codec);
|
||||||
|
~Codec();
|
||||||
|
|
||||||
|
operator AVCodecContext*() const;
|
||||||
|
|
||||||
|
int width() const;
|
||||||
|
int height() const;
|
||||||
|
AVRational timeBase() const;
|
||||||
|
int capabilities() const;
|
||||||
|
AVPixelFormat pixelFormat() const;
|
||||||
|
|
||||||
|
void setWidth(int width);
|
||||||
|
void setHeight(int height);
|
||||||
|
void setPixelFormat(AVPixelFormat pixelFormat);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //FFCONV_CODEC_H
|
||||||
107
ffcpp/MediaFile.cpp
Normal file
107
ffcpp/MediaFile.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "MediaFile.h"
|
||||||
|
#include "ffcpp.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace ffcpp {
|
||||||
|
|
||||||
|
MediaFile::MediaFile(const std::string& src, Mode mode) {
|
||||||
|
_mode = mode;
|
||||||
|
if(mode == Mode::Read) {
|
||||||
|
int res = avformat_open_input(&_formatCtx, src.c_str(), nullptr, nullptr);
|
||||||
|
throwIfError(res, "cannot open input file");
|
||||||
|
|
||||||
|
res = avformat_find_stream_info(_formatCtx, nullptr);
|
||||||
|
throwIfError(res, "cannot find stream info");
|
||||||
|
} else if(mode == Mode::Write) {
|
||||||
|
int res = avformat_alloc_output_context2(&_formatCtx, nullptr, nullptr, src.c_str());
|
||||||
|
throwIfError(res, "cannot allocate format context");
|
||||||
|
|
||||||
|
if (!(_formatCtx->oformat->flags & AVFMT_NOFILE)) {
|
||||||
|
res = avio_open(&_formatCtx->pb, src.c_str(), AVIO_FLAG_WRITE);
|
||||||
|
throwIfError(res, "cannot init avio context");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
|
||||||
|
_formatCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||||
|
|
||||||
|
av_dump_format(_formatCtx, 0, src.c_str(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaFile::hasStream(AVMediaType type) const {
|
||||||
|
for(size_t i = 0; i < _formatCtx->nb_streams; ++i) {
|
||||||
|
if(_formatCtx->streams[i]->codec->codec_type == type) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaFile::hasVideo() const {
|
||||||
|
return hasStream(AVMEDIA_TYPE_VIDEO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaFile::hasAudio() const {
|
||||||
|
return hasStream(AVMEDIA_TYPE_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream MediaFile::getStream(AVMediaType type, size_t index) const {
|
||||||
|
for(size_t i = 0, curIndex = 0; i < _formatCtx->nb_streams; ++i) {
|
||||||
|
if(_formatCtx->streams[i]->codec->codec_type == type) {
|
||||||
|
if(curIndex == index) {
|
||||||
|
return Stream(_formatCtx->streams[i]);
|
||||||
|
} else {
|
||||||
|
curIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("cannot find stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream MediaFile::videoStream(size_t index /* = 0 */) const {
|
||||||
|
return getStream(AVMEDIA_TYPE_VIDEO, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream MediaFile::audioStream(size_t index /* = 0 */) const {
|
||||||
|
return getStream(AVMEDIA_TYPE_AUDIO, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaFile::operator AVFormatContext*() const {
|
||||||
|
return _formatCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaFile::~MediaFile() {
|
||||||
|
if(_mode == Mode::Write) {
|
||||||
|
avformat_free_context(_formatCtx);
|
||||||
|
} else {
|
||||||
|
avformat_close_input(&_formatCtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream MediaFile::addStream(AVCodecID codecID, int width, int height, AVPixelFormat pixelFormat) {
|
||||||
|
AVCodec* codec = avcodec_find_encoder(codecID);
|
||||||
|
if(!codec) throw std::runtime_error("cannot find codec");
|
||||||
|
|
||||||
|
AVStream* stream = avformat_new_stream(_formatCtx, codec);
|
||||||
|
if(!stream) throw std::runtime_error("cannot create stream");
|
||||||
|
|
||||||
|
AVCodecContext* ctx = stream->codec;
|
||||||
|
ctx->width = width;
|
||||||
|
ctx->height = height;
|
||||||
|
ctx->pix_fmt = pixelFormat;
|
||||||
|
|
||||||
|
return Stream(stream, codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaFile::writeHeader() {
|
||||||
|
int res = avformat_write_header(_formatCtx, nullptr);
|
||||||
|
throwIfError(res, "error writing header");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaFile::writeTrailer() {
|
||||||
|
int res = av_write_trailer(_formatCtx);
|
||||||
|
throwIfError(res, "error writing trailer");
|
||||||
|
}
|
||||||
|
}
|
||||||
47
ffcpp/MediaFile.h
Normal file
47
ffcpp/MediaFile.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef FFCONV_MEDIAFILE_H
|
||||||
|
#define FFCONV_MEDIAFILE_H
|
||||||
|
|
||||||
|
#include "Stream.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ffcpp {
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
Read,
|
||||||
|
Write
|
||||||
|
};
|
||||||
|
|
||||||
|
class MediaFile {
|
||||||
|
private:
|
||||||
|
AVFormatContext* _formatCtx;
|
||||||
|
Mode _mode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MediaFile(const std::string& src, Mode mode);
|
||||||
|
|
||||||
|
operator AVFormatContext*() const;
|
||||||
|
|
||||||
|
bool hasVideo() const;
|
||||||
|
bool hasAudio() const;
|
||||||
|
Stream videoStream(size_t index = 0) const;
|
||||||
|
Stream audioStream(size_t index = 0) const;
|
||||||
|
Stream addStream(AVCodecID codecID, int width, int height, AVPixelFormat pixelFormat);
|
||||||
|
|
||||||
|
void writeHeader();
|
||||||
|
void writeTrailer();
|
||||||
|
|
||||||
|
~MediaFile();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool hasStream(AVMediaType type) const;
|
||||||
|
Stream getStream(AVMediaType type, size_t index) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //FFCONV_MEDIAFILE_H
|
||||||
36
ffcpp/Stream.cpp
Normal file
36
ffcpp/Stream.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "Stream.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace ffcpp {
|
||||||
|
|
||||||
|
Stream::Stream() {
|
||||||
|
_stream = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream::Stream(AVStream *stream) {
|
||||||
|
_stream = stream;
|
||||||
|
_codec = Codec(_stream->codec, CodecType::Decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream::Stream(AVStream *stream, AVCodec* encoder) {
|
||||||
|
_stream = stream;
|
||||||
|
_codec = Codec(stream->codec, encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream::operator AVStream*() const {
|
||||||
|
return _stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
Codec Stream::codec() const {
|
||||||
|
return _codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVRational Stream::timeBase() const {
|
||||||
|
return _stream->time_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stream::setTimeBase(AVRational timeBase) {
|
||||||
|
_stream->time_base = timeBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
30
ffcpp/Stream.h
Normal file
30
ffcpp/Stream.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef FFCONV_STREAM_H
|
||||||
|
#define FFCONV_STREAM_H
|
||||||
|
|
||||||
|
#include "Codec.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ffcpp {
|
||||||
|
|
||||||
|
class Stream {
|
||||||
|
private:
|
||||||
|
AVStream* _stream;
|
||||||
|
Codec _codec;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Stream();
|
||||||
|
Stream(AVStream* stream);
|
||||||
|
Stream(AVStream* stream, AVCodec* encoder);
|
||||||
|
operator AVStream*() const;
|
||||||
|
Codec codec() const;
|
||||||
|
|
||||||
|
AVRational timeBase() const;
|
||||||
|
void setTimeBase(AVRational timeBase);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //FFCONV_STREAM_H
|
||||||
22
ffcpp/ffcpp.cpp
Normal file
22
ffcpp/ffcpp.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "ffcpp.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ffcpp {
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
av_register_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void throwIfError(int result, const std::string& description) {
|
||||||
|
if(result < 0) {
|
||||||
|
char errStr[260];
|
||||||
|
av_strerror(result, errStr, 260);
|
||||||
|
throw std::runtime_error(description + ": " + errStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
13
ffcpp/ffcpp.h
Normal file
13
ffcpp/ffcpp.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef FFCONV_FFCPP_H
|
||||||
|
#define FFCONV_FFCPP_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ffcpp {
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void throwIfError(int result, const std::string& description);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //FFCONV_FFCPP_H
|
||||||
110
main.cpp
110
main.cpp
@ -1,4 +1,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "ffcpp/ffcpp.h"
|
||||||
|
#include "ffcpp/MediaFile.h"
|
||||||
|
#include "ffcpp/Stream.h"
|
||||||
|
#include "ffcpp/Codec.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
@ -12,69 +16,23 @@ void checkResult(int res, const char* msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ff = ffcpp;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
AVFormatContext* inFmtCtx = nullptr;
|
ff::init();
|
||||||
AVFormatContext* outFmtCtx = nullptr;
|
ff::MediaFile input(argv[1], ff::Mode::Read);
|
||||||
|
ff::MediaFile output(argv[2], ff::Mode::Write);
|
||||||
|
|
||||||
av_register_all();
|
ff::Stream vStream;
|
||||||
int res = avformat_open_input(&inFmtCtx, argv[1], nullptr, nullptr);
|
if(input.hasVideo()) {
|
||||||
checkResult(res, "cannot open input");
|
vStream = input.videoStream();
|
||||||
|
|
||||||
res = avformat_find_stream_info(inFmtCtx, nullptr);
|
|
||||||
checkResult(res, "cannot find stream info");
|
|
||||||
|
|
||||||
res = avformat_alloc_output_context2(&outFmtCtx, nullptr, nullptr, argv[2]);
|
|
||||||
checkResult(res, "cannot allocate output context");
|
|
||||||
|
|
||||||
AVStream *videoStream = nullptr, *audioStream = nullptr;
|
|
||||||
for(int i = 0; i < inFmtCtx->nb_streams; ++i) {
|
|
||||||
AVStream* stream = inFmtCtx->streams[i];
|
|
||||||
if(stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
||||||
std::cout << "found video stream " << avcodec_get_name(stream->codec->codec_id) << std::endl;
|
|
||||||
videoStream = stream;
|
|
||||||
} else if(stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
|
|
||||||
std::cout << "found audio stream " << avcodec_get_name(stream->codec->codec_id) << std::endl;
|
|
||||||
audioStream = stream;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AVCodecContext* codecCtx = videoStream->codec;
|
ff::Codec vDecoder = vStream.codec();
|
||||||
AVCodec* codec = avcodec_find_decoder(codecCtx->codec_id);
|
ff::Stream outVStream = output.addStream(AV_CODEC_ID_H264, vDecoder.width(), vDecoder.height(), AV_PIX_FMT_YUV420P);
|
||||||
if(!codec) std::cout << "cannot find decoder" << std::endl;
|
outVStream.setTimeBase(vDecoder.timeBase());
|
||||||
|
ff::Codec vEncoder = outVStream.codec();
|
||||||
res = avcodec_open2(codecCtx, codec, nullptr);
|
output.writeHeader();
|
||||||
checkResult(res, "cannot open codec for decoding");
|
|
||||||
|
|
||||||
// coder
|
|
||||||
AVCodec* dstVCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
|
|
||||||
if(!dstVCodec) std::cout << "cannot find encoder" << std::endl;
|
|
||||||
|
|
||||||
AVStream* outVideoStream = avformat_new_stream(outFmtCtx, dstVCodec);
|
|
||||||
if(!outVideoStream) std::cout << "cannot create output video stream" << std::endl;
|
|
||||||
|
|
||||||
if (!(outFmtCtx->oformat->flags & AVFMT_NOFILE)) {
|
|
||||||
res = avio_open(&outFmtCtx->pb, argv[2], AVIO_FLAG_WRITE);
|
|
||||||
checkResult(res, "cannot open output file");
|
|
||||||
}
|
|
||||||
|
|
||||||
av_dump_format(outFmtCtx, 0, argv[2], 1);
|
|
||||||
|
|
||||||
AVCodecContext* dstVCodecCtx = outVideoStream->codec;
|
|
||||||
dstVCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
|
|
||||||
dstVCodecCtx->width = codecCtx->width;
|
|
||||||
dstVCodecCtx->height = codecCtx->height;
|
|
||||||
//dstVCodecCtx->time_base = codecCtx->time_base;
|
|
||||||
outVideoStream->time_base = codecCtx->time_base;
|
|
||||||
outFmtCtx->duration = inFmtCtx->duration;
|
|
||||||
|
|
||||||
if(outFmtCtx->oformat->flags & AVFMT_GLOBALHEADER)
|
|
||||||
dstVCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
|
||||||
|
|
||||||
res = avcodec_open2(dstVCodecCtx, dstVCodec, nullptr);
|
|
||||||
checkResult(res, "cannot open codec for encoding");
|
|
||||||
|
|
||||||
res = avformat_write_header(outFmtCtx, nullptr);
|
|
||||||
checkResult(res, "error writing header to output file");
|
|
||||||
|
|
||||||
AVFrame* frame = nullptr;
|
AVFrame* frame = nullptr;
|
||||||
int gotPicture = 0, gotPacket = 0, decodedFrames = 1;
|
int gotPicture = 0, gotPacket = 0, decodedFrames = 1;
|
||||||
@ -83,15 +41,15 @@ int main(int argc, char** argv) {
|
|||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
packet.data = nullptr;
|
packet.data = nullptr;
|
||||||
packet.size = 0;
|
packet.size = 0;
|
||||||
res = av_read_frame(inFmtCtx, &packet);
|
int res = av_read_frame(input, &packet);
|
||||||
if(res < 0) break;
|
if(res < 0) break;
|
||||||
|
|
||||||
frame = av_frame_alloc();
|
frame = av_frame_alloc();
|
||||||
if(!frame) break;
|
if(!frame) break;
|
||||||
|
|
||||||
AVMediaType packetType = inFmtCtx->streams[packet.stream_index]->codec->codec_type;
|
AVMediaType packetType = ((AVFormatContext*)input)->streams[packet.stream_index]->codec->codec_type;
|
||||||
if(packetType == AVMEDIA_TYPE_VIDEO) {
|
if(packetType == AVMEDIA_TYPE_VIDEO) {
|
||||||
res = avcodec_decode_video2(codecCtx, frame, &gotPicture, &packet);
|
res = avcodec_decode_video2(vDecoder, frame, &gotPicture, &packet);
|
||||||
if(res < 0) {
|
if(res < 0) {
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
break;
|
break;
|
||||||
@ -108,7 +66,7 @@ int main(int argc, char** argv) {
|
|||||||
av_init_packet(&encPacket);
|
av_init_packet(&encPacket);
|
||||||
encPacket.stream_index = 0;
|
encPacket.stream_index = 0;
|
||||||
|
|
||||||
res = avcodec_encode_video2(dstVCodecCtx, &encPacket, frame, &gotPacket);
|
res = avcodec_encode_video2(vEncoder, &encPacket, frame, &gotPacket);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
if(res < 0) break;
|
if(res < 0) break;
|
||||||
if(!gotPacket) continue;
|
if(!gotPacket) continue;
|
||||||
@ -127,9 +85,9 @@ int main(int argc, char** argv) {
|
|||||||
oldPts = encPacket.pts;
|
oldPts = encPacket.pts;
|
||||||
oldDts = encPacket.dts;
|
oldDts = encPacket.dts;
|
||||||
|
|
||||||
av_packet_rescale_ts(&encPacket, videoStream->time_base, outVideoStream->time_base);
|
av_packet_rescale_ts(&encPacket, vStream.timeBase(), outVStream.timeBase());
|
||||||
|
|
||||||
res = av_interleaved_write_frame(outFmtCtx, &encPacket);
|
res = av_interleaved_write_frame(output, &encPacket);
|
||||||
checkResult(res, "cannot write frame to output file");
|
checkResult(res, "cannot write frame to output file");
|
||||||
if(res < 0) break;
|
if(res < 0) break;
|
||||||
}
|
}
|
||||||
@ -139,7 +97,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// flush encoder
|
// flush encoder
|
||||||
if(dstVCodecCtx->codec->capabilities & AV_CODEC_CAP_DELAY) {
|
if(vEncoder.capabilities() & AV_CODEC_CAP_DELAY) {
|
||||||
std::cout << "flushing encoder" << std::endl;
|
std::cout << "flushing encoder" << std::endl;
|
||||||
int gotFrame = 0;
|
int gotFrame = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -148,15 +106,15 @@ int main(int argc, char** argv) {
|
|||||||
encPacket.size = 0;
|
encPacket.size = 0;
|
||||||
av_init_packet(&encPacket);
|
av_init_packet(&encPacket);
|
||||||
encPacket.stream_index = 0;
|
encPacket.stream_index = 0;
|
||||||
res = avcodec_encode_video2(dstVCodecCtx, &encPacket, nullptr, &gotFrame);
|
int res = avcodec_encode_video2(vEncoder, &encPacket, nullptr, &gotFrame);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
std::cout << "avcodec_encode_video2 failed" << std::endl;
|
std::cout << "avcodec_encode_video2 failed" << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (gotFrame) {
|
if (gotFrame) {
|
||||||
//std::cout << "extra frame" << std::endl;
|
//std::cout << "extra frame" << std::endl;
|
||||||
av_packet_rescale_ts(&encPacket, videoStream->time_base, outVideoStream->time_base);
|
av_packet_rescale_ts(&encPacket, vStream.timeBase(), outVStream.timeBase());
|
||||||
res = av_interleaved_write_frame(outFmtCtx, &encPacket);
|
res = av_interleaved_write_frame(output, &encPacket);
|
||||||
checkResult(res, "[flush encoder] cannot write frame to output file");
|
checkResult(res, "[flush encoder] cannot write frame to output file");
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -164,19 +122,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = av_write_trailer(outFmtCtx);
|
output.writeTrailer();
|
||||||
checkResult(res, "error writing trailer to output file");
|
|
||||||
|
|
||||||
if(codecCtx)
|
|
||||||
avcodec_close(codecCtx);
|
|
||||||
|
|
||||||
if(dstVCodecCtx)
|
|
||||||
avcodec_close(dstVCodecCtx);
|
|
||||||
|
|
||||||
if(inFmtCtx)
|
|
||||||
avformat_close_input(&inFmtCtx);
|
|
||||||
|
|
||||||
avformat_free_context(outFmtCtx);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user