diff --git a/CMakeLists.txt b/CMakeLists.txt index 5013326..67eadb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,6 @@ link_directories(${FFMPEG_LIBRARY_DIRS}) #message(FATAL_ERROR ${FFMPEG_LIBRARIES}) -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) +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 ffcpp/Packet.cpp ffcpp/Packet.h) add_executable(ffConv ${SOURCE_FILES}) target_link_libraries(ffConv ${FFMPEG_LIBRARIES}) \ No newline at end of file diff --git a/ffcpp/Codec.cpp b/ffcpp/Codec.cpp index c6745a4..2a3e6a1 100644 --- a/ffcpp/Codec.cpp +++ b/ffcpp/Codec.cpp @@ -30,7 +30,9 @@ namespace ffcpp { } Codec::~Codec() { - //avcodec_close(_codecCtx); + if(_codecCtx) { + avcodec_close(_codecCtx); + } } Codec::operator AVCodecContext*() const { @@ -69,4 +71,16 @@ namespace ffcpp { _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; + } + } diff --git a/ffcpp/Codec.h b/ffcpp/Codec.h index ba8e45a..e1728be 100644 --- a/ffcpp/Codec.h +++ b/ffcpp/Codec.h @@ -34,6 +34,10 @@ namespace ffcpp { void setWidth(int width); void setHeight(int height); void setPixelFormat(AVPixelFormat pixelFormat); + + public: + Codec(Codec&& c); + Codec& operator=(Codec&& c); }; } diff --git a/ffcpp/MediaFile.cpp b/ffcpp/MediaFile.cpp index 6201113..2011a25 100644 --- a/ffcpp/MediaFile.cpp +++ b/ffcpp/MediaFile.cpp @@ -12,6 +12,10 @@ namespace ffcpp { res = avformat_find_stream_info(_formatCtx, nullptr); throwIfError(res, "cannot find stream info"); + + for(size_t i = 0; i < _formatCtx->nb_streams; ++i) { + _streams.push_back(Stream(_formatCtx->streams[i])); + } } else if(mode == Mode::Write) { int res = avformat_alloc_output_context2(&_formatCtx, nullptr, nullptr, src.c_str()); throwIfError(res, "cannot allocate format context"); @@ -46,11 +50,11 @@ namespace ffcpp { return hasStream(AVMEDIA_TYPE_AUDIO); } - Stream MediaFile::getStream(AVMediaType type, size_t index) const { + Stream& MediaFile::getStream(AVMediaType type, size_t index) { 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]); + return _streams[i]; } else { curIndex++; } @@ -60,11 +64,11 @@ namespace ffcpp { throw std::runtime_error("cannot find stream"); } - Stream MediaFile::videoStream(size_t index /* = 0 */) const { + Stream& MediaFile::videoStream(size_t index /* = 0 */) { return getStream(AVMEDIA_TYPE_VIDEO, index); } - Stream MediaFile::audioStream(size_t index /* = 0 */) const { + Stream& MediaFile::audioStream(size_t index /* = 0 */) { return getStream(AVMEDIA_TYPE_AUDIO, index); } @@ -80,7 +84,7 @@ namespace ffcpp { } } - Stream MediaFile::addStream(AVCodecID codecID, int width, int height, AVPixelFormat pixelFormat) { + 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"); @@ -92,7 +96,8 @@ namespace ffcpp { ctx->height = height; ctx->pix_fmt = pixelFormat; - return Stream(stream, codec); + _streams.push_back(Stream(stream, codec)); + return _streams.back(); } void MediaFile::writeHeader() { diff --git a/ffcpp/MediaFile.h b/ffcpp/MediaFile.h index 33763cf..46f7682 100644 --- a/ffcpp/MediaFile.h +++ b/ffcpp/MediaFile.h @@ -2,12 +2,14 @@ #define FFCONV_MEDIAFILE_H #include "Stream.h" +#include "Packet.h" extern "C" { #include } #include +#include namespace ffcpp { @@ -20,6 +22,7 @@ namespace ffcpp { private: AVFormatContext* _formatCtx; Mode _mode; + std::vector _streams; public: MediaFile(const std::string& src, Mode mode); @@ -28,9 +31,10 @@ namespace ffcpp { 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); + Stream& videoStream(size_t index = 0); + Stream& audioStream(size_t index = 0); + Stream& addStream(AVCodecID codecID, int width, int height, AVPixelFormat pixelFormat); + void writeHeader(); void writeTrailer(); @@ -39,7 +43,7 @@ namespace ffcpp { private: bool hasStream(AVMediaType type) const; - Stream getStream(AVMediaType type, size_t index) const; + Stream& getStream(AVMediaType type, size_t index); }; } diff --git a/ffcpp/Packet.cpp b/ffcpp/Packet.cpp new file mode 100644 index 0000000..2f07ebc --- /dev/null +++ b/ffcpp/Packet.cpp @@ -0,0 +1,10 @@ +#include "Packet.h" + +namespace ffcpp { + + Packet::Packet() { + _packet.data = nullptr; + _packet.size = 0; + } + +} diff --git a/ffcpp/Packet.h b/ffcpp/Packet.h new file mode 100644 index 0000000..1c5fe6a --- /dev/null +++ b/ffcpp/Packet.h @@ -0,0 +1,20 @@ +#ifndef FFCONV_PACKET_H +#define FFCONV_PACKET_H + +extern "C" { + #include +} + +namespace ffcpp { + + class Packet { + private: + AVPacket _packet; + + public: + Packet(); + }; + +} + +#endif //FFCONV_PACKET_H diff --git a/ffcpp/Stream.cpp b/ffcpp/Stream.cpp index 29dbdbc..45aa1a2 100644 --- a/ffcpp/Stream.cpp +++ b/ffcpp/Stream.cpp @@ -3,25 +3,23 @@ namespace ffcpp { - Stream::Stream() { - _stream = nullptr; + Stream::Stream(): _stream(nullptr) { + } - Stream::Stream(AVStream *stream) { - _stream = stream; - _codec = Codec(_stream->codec, CodecType::Decoder); + Stream::Stream(AVStream *stream): _stream(stream), _codec(_stream->codec, CodecType::Decoder) { + } - Stream::Stream(AVStream *stream, AVCodec* encoder) { - _stream = stream; - _codec = Codec(stream->codec, encoder); + Stream::Stream(AVStream *stream, AVCodec* encoder): _stream(stream), _codec(stream->codec, encoder) { + } Stream::operator AVStream*() const { return _stream; } - Codec Stream::codec() const { + Codec& Stream::codec() { return _codec; } @@ -33,4 +31,15 @@ namespace ffcpp { _stream->time_base = timeBase; } + Stream::Stream(Stream&& stream) { + *this = std::move(stream); + } + + Stream& Stream::operator=(Stream&& stream) { + _codec = std::move(stream._codec); + _stream = stream._stream; + stream._stream = nullptr; + return *this; + } + } diff --git a/ffcpp/Stream.h b/ffcpp/Stream.h index f99d5ab..89f77b7 100644 --- a/ffcpp/Stream.h +++ b/ffcpp/Stream.h @@ -19,10 +19,14 @@ namespace ffcpp { Stream(AVStream* stream); Stream(AVStream* stream, AVCodec* encoder); operator AVStream*() const; - Codec codec() const; + Codec& codec(); AVRational timeBase() const; void setTimeBase(AVRational timeBase); + + public: + Stream(Stream&& stream); + Stream& operator=(Stream&& stream); }; } diff --git a/main.cpp b/main.cpp index 55ff8ad..b90dcef 100644 --- a/main.cpp +++ b/main.cpp @@ -23,15 +23,12 @@ int main(int argc, char** argv) { ff::MediaFile input(argv[1], ff::Mode::Read); ff::MediaFile output(argv[2], ff::Mode::Write); - ff::Stream vStream; - if(input.hasVideo()) { - vStream = input.videoStream(); - } + ff::Stream& vStream = input.videoStream(); - ff::Codec vDecoder = vStream.codec(); - ff::Stream outVStream = output.addStream(AV_CODEC_ID_H264, vDecoder.width(), vDecoder.height(), AV_PIX_FMT_YUV420P); + ff::Codec& vDecoder = vStream.codec(); + ff::Stream& outVStream = output.addStream(AV_CODEC_ID_H264, vDecoder.width(), vDecoder.height(), AV_PIX_FMT_YUV420P); outVStream.setTimeBase(vDecoder.timeBase()); - ff::Codec vEncoder = outVStream.codec(); + ff::Codec& vEncoder = outVStream.codec(); output.writeHeader(); AVFrame* frame = nullptr;