https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff
#ifndef __CSWS_H__
#define __CSWS_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h> // av_image_alloc
#ifdef __cplusplus
}
#endif
#include <string>
#include <mutex>
class CSws
{
public:
~CSws();
// 状态
enum STATUS { STOP, LOCKED };
// 设置源参数
bool set_src_opt(AVPixelFormat pixfmt, int w, int h, std::string& err);
// 设置目标参数
bool set_dst_opt(AVPixelFormat pixfmt, int w, int h, std::string& err);
// 锁定设置
bool lock_opt(std::string& err);
// 解除锁定
bool unlock_opt(std::string& err);
// 转换
bool scale(const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[], std::string& err);
private:
STATUS status_ = STOP;
std::recursive_mutex mutex_;
SwsContext* swsctx_ = nullptr;
AVPixelFormat src_pix_fmt_ = AV_PIX_FMT_NONE;
AVPixelFormat dst_pix_fmt_ = AV_PIX_FMT_NONE;
int src_w_ = 0;
int src_h_ = 0;
int dst_w_ = 0;
int dst_h_ = 0;
};
#endif//__CSWS_H__
#include "common.h"
#include "CSws.h"
CSws::~CSws()
{
std::string err;
unlock_opt(err);
}
bool CSws::set_src_opt(AVPixelFormat pixfmt, int w, int h, std::string& err)
{
LOCK();
CHECKSTOP(err);
src_pix_fmt_ = pixfmt;
src_w_ = w;
src_h_ = h;
return true;
}
bool CSws::set_dst_opt(AVPixelFormat pixfmt, int w, int h, std::string& err)
{
LOCK();
CHECKSTOP(err);
dst_pix_fmt_ = pixfmt;
dst_w_ = w;
dst_h_ = h;
return true;
}
bool CSws::lock_opt(std::string& err)
{
LOCK();
CHECKSTOP(err);
swsctx_ = sws_getContext(src_w_, src_h_, src_pix_fmt_, dst_w_, dst_h_, dst_pix_fmt_, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
if (swsctx_ == nullptr)
{
err = "sws_getContext(src_w_, src_h_, src_pix_fmt_, dst_w_, dst_h_, dst_pix_fmt_, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr) return nullptr.";
return false;
}
status_ = LOCKED;
return true;
}
bool CSws::unlock_opt(std::string& err)
{
LOCK();
sws_freeContext(swsctx_);
swsctx_ = nullptr;
status_ = STOP;
src_w_ = 0;
src_h_ = 0;
dst_w_ = 0;
dst_h_ = 0;
return true;
}
bool CSws::scale(const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[], std::string& err)
{
LOCK();
CHECKNOTSTOP(err);
int ret = sws_scale(swsctx_, srcSlice, srcStride, srcSliceY, srcSliceH, dst, dstStride);
CHECKFFRET(ret);
return true;
}
#include "CDecode.h"
#include "CSws.h"
#include <iostream>
#include <fstream>
CSws g_sws;
uint8_t* g_pointers[4] = { 0 };
int g_linesizes[4] = { 0 };
void DecStatusCB(CDecode::STATUS status, std::string err, void* param)
{
std::cout << std::this_thread::get_id() << " got a status " << status << std::endl;
}
void DecFrameCB(const AVFrame* frame, CDecode::FRAMETYPE frametype, void* param)
{
//std::cout << std::this_thread::get_id() << " got a frame." << frametype << std::endl;
if (frametype == CDecode::FRAMETYPE::VIDEO)
{
if (frame->format == AV_PIX_FMT_YUV420P)
{
static std::ofstream video("out.rgb", std::ios::binary | std::ios::trunc);
static int i = 0;
if (++i > 9)
return;
/*
video.write(reinterpret_cast<const char*>(frame->data[0]), frame->linesize[0] * frame->height);
video.write(reinterpret_cast<const char*>(frame->data[1]), frame->linesize[1] * frame->height / 2);
video.write(reinterpret_cast<const char*>(frame->data[2]), frame->linesize[2] * frame->height / 2);
*/
std::string err;
// 将输出翻转
g_pointers[0] += g_linesizes[0] * (240 - 1);
g_linesizes[0] *= -1;
// 转换
g_sws.scale(frame->data, frame->linesize, 0, frame->height, g_pointers, g_linesizes, err);
// 还原指针,以便拷贝数据
g_linesizes[0] *= -1;
g_pointers[0] -= g_linesizes[0] * (240 - 1);
video.write(reinterpret_cast<const char*>(g_pointers[0]), g_linesizes[0] * 240);
}
}
}
int main(int argc, char* argv[])
{
std::string err;
bool ret = false;
ret = g_sws.set_src_opt(AV_PIX_FMT_YUV420P, 576, 432, err);
ret = g_sws.set_dst_opt(AV_PIX_FMT_RGB24, 320, 240, err);
ret = g_sws.lock_opt(err);
int size = av_image_alloc(g_pointers, g_linesizes, 320, 240, AV_PIX_FMT_RGB24, 1);
CDecode decode;
ret = decode.set_input("in.flv", err);
ret = decode.set_dec_callback(DecFrameCB, nullptr, err);
ret = decode.set_dec_status_callback(DecStatusCB, nullptr, err);
int i = 0;
while (i++ < 1)
{
ret = decode.begindecode(err);
std::cout << "input to stop decoding." << std::endl;
getchar();
ret = decode.stopdecode(err);
}
ret = g_sws.unlock_opt(err);
av_freep(&g_pointers[0]);
return 0;
}