首页 > 解决方案 > 使用 FFmpeg 解码 YUYV422 原始图像

问题描述

我有一组顺序的 YUYV422 原始图像,我希望将其转换为视频。问题似乎是当在avcodec_receive_frame. 该帧仅包含一个通道而不是 YUYV 格式的四个通道。这导致Input picture width <640> is greater then stride (0)因为只有第零个数据索引和行大小设置在帧中。我不知道这是 ffmpeg 错误还是我的错误配置。

#include "icsFfmpegImageDecoder.h"
#include <stdexcept>

ImageDecoder::ImageDecoder(std::string filename)
{
    AVInputFormat* iformat;
    if (!(iformat = av_find_input_format("image2")))
        throw std::invalid_argument(std::string("input Codec not found\n"));

    this->fctx = NULL;
    if (avformat_open_input(&this->fctx, filename.c_str(), iformat, NULL) < 0)
    {
        std::string error = "Failed to open input file ";
        error += filename;
        error += "\n";
        throw std::invalid_argument(error);
    }
#ifdef LIB_AVFORMAT_STREAM_CODEC_DEPRECATED
    if (!(this->codec = avcodec_find_decoder(this->fctx->streams[0]->codecpar->codec_id)))
        throw std::invalid_argument(std::string("Failed to find codec\n"));

    if (!(this->cctx = avcodec_alloc_context3(this->codec)))
        throw std::invalid_argument(std::string("could not create image read context codec"));

    if (avcodec_parameters_to_context(this->cctx, this->fctx->streams[0]->codecpar) < 0)
        throw std::invalid_argument(std::string("could not get contest codec from stream"));
#else
    this->cctx = this->fctx->streams[0]->codec;
    if (!(this->codec = avcodec_find_decoder(this->cctx->codec_id)))
        throw std::invalid_argument(std::string("Failed to find codec\n"));
#endif

    if (this->cctx->codec_id == AV_CODEC_ID_RAWVIDEO) {
        // TODO Make Dynamic
        this->cctx->pix_fmt = AV_PIX_FMT_YUYV422 ;
        this->cctx->height = 800;
        this->cctx->width = 1280;
    }

    if (avcodec_open2(this->cctx, this->codec, NULL) < 0)
        throw std::invalid_argument(std::string("Failed to open codec\n"));

#ifdef USING_NEW_AVPACKET_SETUP
    if (!(this->pkt = av_packet_alloc()))
        throw std::invalid_argument(std::string("Failed to alloc frame\n"));
#else
    this->pkt = new AVPacket();
    av_init_packet(this->pkt);
#endif
    read_file();
}

ImageDecoder::~ImageDecoder()
{
    avcodec_close(this->cctx);
    avformat_close_input(&this->fctx);
#ifdef USING_NEW_AVPACKET_SETUP
    av_packet_free(&this->pkt);
#else
    av_free_packet(this->pkt);
    delete this->pkt;
#endif
}

void ImageDecoder::read_file()
{
    if (av_read_frame(this->fctx, this->pkt) < 0)
        throw std::invalid_argument(std::string("Failed to read frame from file\n"));

    if (this->pkt->size == 0)   
        this->ret = -1;
}

#ifdef LIB_AVCODEC_USE_SEND_RECEIVE_NOTATION
void ImageDecoder::send_next_packet() {

    if ((this->ret = avcodec_send_packet(this->cctx, this->pkt)) < 0)
        throw std::invalid_argument("Error sending a packet for decoding\n");
}

bool ImageDecoder::receive_next_frame(AVFrame* frame)
{
    if (this->ret >= 0)
    {
        this->ret = avcodec_receive_frame(this->cctx, frame);
        if (this->ret == AVERROR_EOF)
            return false;
        else if (this->ret == AVERROR(11))//11 == EAGAIN builder sucks
            return false;
        else if (this->ret < 0)
            throw std::invalid_argument("Error during decoding\n");
        return true;
    }
    return false;
}
#else
void ImageDecoder::decode_frame(AVFrame* frame)
{
    int got_frame = 0;
    if (avcodec_decode_video2(this->cctx, frame, &got_frame, this->pkt) < 0) 
        throw std::invalid_argument("Error while decoding frame %d\n");
}
#endif

标签: c++ffmpeg

解决方案


推荐阅读