added scaling support
This commit is contained in:
parent
a9e042eb4f
commit
1bb9d908da
@ -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 ffcpp/Packet.cpp ffcpp/Packet.h ffcpp/Frame.cpp ffcpp/Frame.h ffcpp/FifoQueue.cpp ffcpp/FifoQueue.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 ffcpp/Frame.cpp ffcpp/Frame.h ffcpp/FifoQueue.cpp ffcpp/FifoQueue.h ffcpp/Scaler.cpp ffcpp/Scaler.h)
|
||||
add_executable(ffConv ${SOURCE_FILES})
|
||||
target_link_libraries(ffConv ${FFMPEG_LIBRARIES})
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
namespace ffcpp {
|
||||
|
||||
Frame::Frame() {
|
||||
Frame::Frame(): _buffer(nullptr) {
|
||||
_frame = av_frame_alloc();
|
||||
}
|
||||
|
||||
@ -19,11 +19,34 @@ namespace ffcpp {
|
||||
throwIfError(res, "cannot initialize buffer in audio frame");
|
||||
}
|
||||
|
||||
Frame::Frame(int width, int height, AVPixelFormat pixelFormat): Frame() {
|
||||
|
||||
/*
|
||||
_frame->width = width;
|
||||
_frame->height = height;
|
||||
_frame->format = pixelFormat;
|
||||
|
||||
int res = av_frame_get_buffer(_frame, 0);
|
||||
throwIfError(res, "cannot initialize buffer in video frame");
|
||||
*/
|
||||
|
||||
_frame->width = width;
|
||||
_frame->height = height;
|
||||
_frame->format = pixelFormat;
|
||||
int size = av_image_get_buffer_size(pixelFormat, width, height, 32);
|
||||
_buffer = (uint8_t*)av_malloc(size*sizeof(uint8_t));
|
||||
int res = av_image_fill_arrays((uint8_t**)_frame->data, _frame->linesize, _buffer, pixelFormat, width, height, 32);
|
||||
throwIfError(res, "cannot initialize video frame");
|
||||
}
|
||||
|
||||
Frame::Frame(Frame &&frame) {
|
||||
*this = std::move(frame);
|
||||
}
|
||||
|
||||
Frame::~Frame() {
|
||||
if(_buffer) {
|
||||
av_free(_buffer);
|
||||
}
|
||||
if(_frame) {
|
||||
av_frame_free(&_frame);
|
||||
}
|
||||
@ -31,7 +54,9 @@ namespace ffcpp {
|
||||
|
||||
Frame& Frame::operator=(Frame&& frame) {
|
||||
_frame = frame._frame;
|
||||
_buffer = frame._buffer;
|
||||
frame._frame = nullptr;
|
||||
frame._buffer = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -3,17 +3,20 @@
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
}
|
||||
|
||||
namespace ffcpp {
|
||||
|
||||
class Frame {
|
||||
private:
|
||||
uint8_t* _buffer;
|
||||
AVFrame* _frame;
|
||||
|
||||
public:
|
||||
Frame();
|
||||
Frame(int size, int channels, AVSampleFormat sampleFormat, int sampleRate);
|
||||
Frame(int width, int height, AVPixelFormat pixelFormat);
|
||||
Frame(Frame&& frame);
|
||||
~Frame();
|
||||
|
||||
|
||||
33
ffcpp/Scaler.cpp
Normal file
33
ffcpp/Scaler.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "Scaler.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ffcpp {
|
||||
|
||||
ffcpp::Scaler::Scaler(int srcWidth, int srcHeight, AVPixelFormat srcPixFmt, int dstWidth, int dstHeight,
|
||||
AVPixelFormat dstPixFmt) {
|
||||
_dstWidth = dstWidth;
|
||||
_dstHeight = dstHeight;
|
||||
_dstPixFmt = dstPixFmt;
|
||||
_swsContext = sws_getContext(srcWidth, srcHeight, srcPixFmt, dstWidth, dstHeight, dstPixFmt, SWS_BICUBIC,
|
||||
nullptr, nullptr, nullptr);
|
||||
if(!_swsContext) {
|
||||
throw new std::runtime_error("cannot create scale context");
|
||||
}
|
||||
}
|
||||
|
||||
Frame Scaler::scale(Frame &inFrame) {
|
||||
Frame outFrame(_dstWidth, _dstHeight, _dstPixFmt);
|
||||
|
||||
AVFrame* fin = inFrame;
|
||||
AVFrame* fout = outFrame;
|
||||
fout->pts = fin->pts;
|
||||
|
||||
int res = sws_scale(_swsContext, (uint8_t const * const *)fin->data, fin->linesize, 0, fin->height, fout->data, fout->linesize);
|
||||
if(res < 0) {
|
||||
throw new std::runtime_error("scale error");
|
||||
}
|
||||
|
||||
return outFrame;
|
||||
}
|
||||
|
||||
}
|
||||
26
ffcpp/Scaler.h
Normal file
26
ffcpp/Scaler.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef FFCONV_SCALER_H
|
||||
#define FFCONV_SCALER_H
|
||||
|
||||
extern "C" {
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
namespace ffcpp {
|
||||
|
||||
class Scaler {
|
||||
private:
|
||||
SwsContext* _swsContext;
|
||||
int _dstHeight;
|
||||
int _dstWidth;
|
||||
AVPixelFormat _dstPixFmt;
|
||||
|
||||
public:
|
||||
Scaler(int srcWidth, int srcHeight, AVPixelFormat srcPixFmt, int dstWidth, int dstHeight, AVPixelFormat dstPixFmt);
|
||||
Frame scale(Frame& inFrame);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //FFCONV_SCALER_H
|
||||
13
main.cpp
13
main.cpp
@ -2,10 +2,14 @@
|
||||
#include "ffcpp/ffcpp.h"
|
||||
#include "ffcpp/MediaFile.h"
|
||||
#include "ffcpp/FifoQueue.h"
|
||||
#include "ffcpp/Scaler.h"
|
||||
|
||||
constexpr int VIDEO_STREAM_INDEX = 0;
|
||||
constexpr int AUDIO_STREAM_INDEX = 1;
|
||||
|
||||
constexpr int VIDEO_WIDTH = 854;
|
||||
constexpr int VIDEO_HEIGHT = 480;
|
||||
|
||||
namespace ff = ffcpp;
|
||||
|
||||
void flushEncoder(ff::MediaFile& file, ff::Codec& encoder, const ff::Stream& inStream, const ff::Stream& outStream, int streamIndex) {
|
||||
@ -32,7 +36,9 @@ int main(int argc, char** argv) {
|
||||
ff::Codec& vDecoder = vStream.codec();
|
||||
ff::Codec& aDecoder = aStream.codec();
|
||||
|
||||
ff::Stream& outVStream = output.addVideoStream(AV_CODEC_ID_H264, vDecoder.width(), vDecoder.height(), AV_PIX_FMT_YUV420P);
|
||||
double aspect = 1.0*vDecoder.width()/vDecoder.height();
|
||||
int outHeight = (int)(VIDEO_WIDTH/aspect) & ~1;
|
||||
ff::Stream& outVStream = output.addVideoStream(AV_CODEC_ID_H264, VIDEO_WIDTH, outHeight, AV_PIX_FMT_YUV420P);
|
||||
ff::Codec& vEncoder = outVStream.codec();
|
||||
|
||||
ff::Stream& outAStream = output.addAudioStream(AV_CODEC_ID_VORBIS, aDecoder.channels(), aDecoder.sampleRate());
|
||||
@ -49,9 +55,11 @@ int main(int argc, char** argv) {
|
||||
|
||||
int64_t aPts = 0;
|
||||
ff::FifoQueue fifo(aEncoder.sampleFormat(), aEncoder.channels(), aEncoder.frameSize());
|
||||
ff::Scaler scaler(vDecoder.width(), vDecoder.height(), vDecoder.pixelFormat(), VIDEO_WIDTH, outHeight, AV_PIX_FMT_YUV420P);
|
||||
while(auto packet = input.readPacket()) {
|
||||
AVMediaType packetType = input.packetType(packet);
|
||||
if(packetType == AVMEDIA_TYPE_AUDIO) {
|
||||
continue;
|
||||
auto frame = aDecoder.decode(packet);
|
||||
fifo.addSamples(frame);
|
||||
if(!fifo.enoughSamples()) continue;
|
||||
@ -69,6 +77,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
} else if(packetType == AVMEDIA_TYPE_VIDEO) {
|
||||
auto frame = vDecoder.decode(packet);
|
||||
frame = scaler.scale(frame);
|
||||
frame.setPictureType(AV_PICTURE_TYPE_NONE);
|
||||
auto encPacket = vEncoder.encode(frame);
|
||||
if(!encPacket) continue;
|
||||
@ -79,7 +88,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
flushEncoder(output, vEncoder, vStream, outVStream, VIDEO_STREAM_INDEX);
|
||||
flushEncoder(output, aEncoder, aStream, outAStream, AUDIO_STREAM_INDEX);
|
||||
//flushEncoder(output, aEncoder, aStream, outAStream, AUDIO_STREAM_INDEX);
|
||||
output.writeTrailer();
|
||||
|
||||
return 0;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user