使用ffmpeg解码raw图

调试过程中,生成了一张raw图,如何显示raw图的内容的,可参考如下的命令

原图16bit 320*240(https://download.csdn.net/download/mike8825/12342954)

ffmpeg -vcodec rawvideo -f rawvideo -pix_fmt rgb565 -s 320*240 -i 1.raw -f image2 -vcodec bmp 1.bmp
原图32bit 1920*1080

ffmpeg -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s 1920x1080 -i 2.raw -f image2 -vcodec bmp 2.bmp
最开始想通过cat /dev/fb0 >2.raw,用2.raw来解码,但解码出来是黑屏的,可能跟显示架构有关系,这里不深究。

参考下面的命令,可以将图片转换成raw图,然后raw在装换成图片,这样就可以验证命令的正确性了。

# rgb8888 -> bmp
ffmpeg -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s 640x480 -i fb.raw -f image2 -vcodec bmp fb.bmp
 
# rgb565 -> bmp
ffmpeg -vcodec rawvideo -f rawvideo -pix_fmt rgb565 -s 640x480 -i fb.raw -f image2 -vcodec bmp fb.bmp
 
# bmp -> rgb8888
ffmpeg -vcodec bmp -i fb.bmp -vcodec rawvideo -f rawvideo -pix_fmt rgb32 fb.raw
 
# bmp -> rgb565
ffmpeg -vcodec bmp -i fb.bmp -vcodec rawvideo -f rawvideo -pix_fmt rgb565 fb.raw
 参考:https://qiita.com/koara-local/items/0b750355b1a9135ff53f

使用ffmpeg解码raw图_那颗流星的博客-CSDN博客_ffmpeg rawvideo调试过程中,生成了一张raw图,如何显示raw图的内容的,可参考如下的命令原图16bit 320*240ffmpeg -vcodec rawvideo -f rawvideo -pix_fmt rgb16 -s 320*240 -i 1.raw -f image2 -vcodec bmp 1.bmp原图32bit 1920*1080ffmpeg -vcodec rawvideo...https://blog.csdn.net/mike8825/article/details/105631968?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&utm_relevant_index=1

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我可以回答这个问题。以下是一份ffmpeg异步解码的代码示例: ``` #include <iostream> #include <thread> #include <mutex> #include <condition_variable> #include <queue> #include <chrono> extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavutil/imgutils.h> #include <libswscale/swscale.h> } using namespace std; // 用于存储解码后的帧 struct Frame { AVFrame* frame; int64_t pts; }; // 解码线程 void decode_thread(AVFormatContext* fmt_ctx, AVCodecContext* codec_ctx, queue<Frame>& frames, mutex& frames_mutex, condition_variable& frames_cv) { AVPacket pkt; av_init_packet(&pkt); pkt.data = nullptr; pkt.size = 0; while (av_read_frame(fmt_ctx, &pkt) >= 0) { if (pkt.stream_index == codec_ctx->stream_index) { int ret = avcodec_send_packet(codec_ctx, &pkt); if (ret < 0) { cerr << "Error sending packet to decoder: " << av_err2str(ret) << endl; break; } while (ret >= 0) { AVFrame* frame = av_frame_alloc(); ret = avcodec_receive_frame(codec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { av_frame_free(&frame); break; } else if (ret < 0) { cerr << "Error receiving frame from decoder: " << av_err2str(ret) << endl; av_frame_free(&frame); break; } Frame f = {frame, av_frame_get_best_effort_timestamp(frame)}; unique_lock<mutex> lock(frames_mutex); frames.push(f); lock.unlock(); frames_cv.notify_one(); } } av_packet_unref(&pkt); } av_packet_unref(&pkt); } // 显示线程 void display_thread(queue<Frame>& frames, mutex& frames_mutex, condition_variable& frames_cv) { AVFrame* frame = nullptr; AVPixelFormat pix_fmt = AV_PIX_FMT_RGBA; int width = 0, height = 0; SwsContext* sws_ctx = nullptr; uint8_t* buffer = nullptr; int buffer_size = 0; while (true) { unique_lock<mutex> lock(frames_mutex); frames_cv.wait(lock, [&frames]{ return !frames.empty(); }); Frame f = frames.front(); frames.pop(); lock.unlock(); if (f.frame) { if (!frame) { width = f.frame->width; height = f.frame->height; pix_fmt = AV_PIX_FMT_RGBA; sws_ctx = sws_getContext(width, height, f.frame->format, width, height, pix_fmt, SWS_BILINEAR, nullptr, nullptr, nullptr); buffer_size = av_image_get_buffer_size(pix_fmt, width, height, 1); buffer = (uint8_t*)av_malloc(buffer_size); } sws_scale(sws_ctx, f.frame->data, f.frame->linesize, 0, height, &buffer, &width); av_frame_free(&f.frame); frame = av_frame_alloc(); av_image_fill_arrays(frame->data, frame->linesize, buffer, pix_fmt, width, height, 1); frame->width = width; frame->height = height; frame->format = pix_fmt; frame->pts = f.pts; // 显示帧 cout << "Displaying frame with PTS " << frame->pts << endl; av_frame_free(&frame); } } av_free(buffer); sws_freeContext(sws_ctx); } int main(int argc, char* argv[]) { if (argc < 2) { cerr << "Usage: " << argv[0] << " <input_file>" << endl; return 1; } av_register_all(); avcodec_register_all(); AVFormatContext* fmt_ctx = nullptr; int ret = avformat_open_input(&fmt_ctx, argv[1], nullptr, nullptr); if (ret < 0) { cerr << "Error opening input file: " << av_err2str(ret) << endl; return 1; } ret = avformat_find_stream_info(fmt_ctx, nullptr); if (ret < 0) { cerr << "Error finding stream information: " << av_err2str(ret) << endl; avformat_close_input(&fmt_ctx); return 1; } AVCodec* codec = nullptr; int stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0); if (stream_index < 0) { cerr << "Error finding video stream: " << av_err2str(stream_index) << endl; avformat_close_input(&fmt_ctx); return 1; } AVCodecContext* codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) { cerr << "Error allocating codec context" << endl; avformat_close_input(&fmt_ctx); return 1; } ret = avcodec_parameters_to_context(codec_ctx, fmt_ctx->streams[stream_index]->codecpar); if (ret < 0) { cerr << "Error setting codec parameters: " << av_err2str(ret) << endl; avcodec_free_context(&codec_ctx); avformat_close_input(&fmt_ctx); return 1; } ret = avcodec_open2(codec_ctx, codec, nullptr); if (ret < 0) { cerr << "Error opening codec: " << av_err2str(ret) << endl; avcodec_free_context(&codec_ctx); avformat_close_input(&fmt_ctx); return 1; } queue<Frame> frames; mutex frames_mutex; condition_variable frames_cv; thread decode_th(decode_thread, fmt_ctx, codec_ctx, ref(frames), ref(frames_mutex), ref(frames_cv)); thread display_th(display_thread, ref(frames), ref(frames_mutex), ref(frames_cv)); decode_th.join(); display_th.join(); avcodec_free_context(&codec_ctx); avformat_close_input(&fmt_ctx); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值