FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws
程序员文章站
2022-04-10 21:53:42
Github https://github.com/gongluck/FFmpeg4.0 study/tree/master/Cff CSws.h CSws.cpp 测试 C++ include "CDecode.h" include "CSws.h" include include CSws g_ ......
github
https://github.com/gongluck/ffmpeg4.0-study/tree/master/cff
csws.h
#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__
csws.cpp
#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; }