https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cffios
#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; }