ffmpeg使用mjpeg把yuvj420p编码为jpg图像

发布于:2024-07-02 ⋅ 阅读:(147) ⋅ 点赞:(0)

version

#define LIBAVCODEC_VERSION_MAJOR  60

#define LIBAVCODEC_VERSION_MINOR  15

#define LIBAVCODEC_VERSION_MICRO 100

node

不使用AVOutputFormat

code

void CFfmpegOps::EncodeYUVJ420pToMJPEG(const char* infile, const char* width_str, const char* height_str, const char* outfile)
{
    if ((!infile) || (!outfile))
    {
        return;
    }

    int32_t width = 0;
    int32_t height = 0;
    FILE *in_fp = nullptr;
    size_t n = 0;
    AVCodecContext *encoder_ctx = nullptr;
    const AVCodec *encoder = nullptr;
    FILE* out_fp = nullptr;
    int ret = -1;
    AVFrame *avframe = nullptr;
    AVPacket *avpacket = nullptr;
    int frame_bytes = 0;

    try
    {
        width = std::stoi(width_str);
        height = std::stoi(height_str);
    }
    catch (std::exception &e)
    {
        return;
    }

    in_fp = fopen(infile, "rb");
    if (!in_fp)
    {
        printf("fopen error\n");
        goto end;
    }

    avframe = av_frame_alloc();
    if (!avframe)
    {
        printf("av_frame_alloc error\n");
        goto end;
    }
    avframe->width = width;
    avframe->height = height;
    avframe->format = AV_PIX_FMT_YUVJ420P;
    avframe->pts = 0;

    // 获取单帧yuvj420p的字节数
    frame_bytes = av_image_get_buffer_size((AVPixelFormat)(avframe->format), avframe->width, avframe->height, 1);

    ret = av_frame_get_buffer(avframe, 0);
    if (ret < 0)
    {
        printf("av_frame_get_buffer error:%s\n", GetFfmpegERR(ret));
        goto end;
    }

    // 读取y分量
    n = fread(avframe->data[0], sizeof(uint8_t), avframe->width * avframe->height, in_fp);
    if ((int)n != (avframe->width * avframe->height))
    {
        printf("n != (avframe->width * avframe->height)\n");
        goto end;
    }

    // 读取u分量
    n = fread(avframe->data[1], sizeof(uint8_t), avframe->width * avframe->height / 4, in_fp);
    if ((int)n != (avframe->width * avframe->height / 4))
    {
        printf("n != (avframe->width * avframe->height / 4)\n");
        goto end;
    }

    // 读取v分量
    n = fread(avframe->data[2], sizeof(uint8_t), avframe->width * avframe->height / 4, in_fp);
    if ((int)n != (avframe->width * avframe->height / 4))
    {
        printf("n != (avframe->width * avframe->height / 4)\n");
        goto end;
    }

    avpacket = av_packet_alloc();
    if (!avpacket)
    {
        printf("av_packet_alloc error\n");
        goto end;
    }

    encoder = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
    if (!encoder)
    {
        printf("avcodec_find_encoder error\n");
        goto end;
    }

    encoder_ctx = avcodec_alloc_context3(encoder);
    if (!encoder_ctx)
    {
        printf("avcodec_alloc_context3 error\n");
        goto end;
    }
    // encoder_ctx->colorspace = ;
    // encoder_ctx->color_range = ;
    encoder_ctx->pix_fmt = AV_PIX_FMT_YUVJ420P;
    encoder_ctx->width = width;
    encoder_ctx->height = height;
    encoder_ctx->framerate.num = 25;
    encoder_ctx->framerate.den = 1;
    encoder_ctx->time_base.num = 1;
    encoder_ctx->time_base.den = 25;
    encoder_ctx->bit_rate = frame_bytes * encoder_ctx->framerate.num * 8;

    ret = avcodec_open2(encoder_ctx, encoder, nullptr);
    if (ret < 0)
    {
        printf("avcodec_open2 error:%s\n", GetFfmpegERR(ret));
        goto end;
    }

    out_fp = fopen(outfile, "wb");
    if (!out_fp)
    {
        printf("avcodec_alloc_context3 error\n");
        goto end;
    }

    ret = avcodec_send_frame(encoder_ctx, avframe);
    if (ret < 0)
    {
        printf("avcodec_send_frame error:%s\n", GetFfmpegERR(ret));
        goto end;
    }

    while (1)
    {
        ret = avcodec_receive_packet(encoder_ctx, avpacket);
        if (ret < 0)
        {
            printf("avcodec_receive_packet error:%s\n", GetFfmpegERR(ret));
            break;
        }

        n = fwrite(avpacket->data, sizeof(uint8_t), avpacket->size, out_fp);
        
    }

end:
    if (avpacket)
    {
        av_packet_free(&avpacket);
        avpacket = nullptr;
    }

    if (avframe)
    {
        av_frame_free(&avframe);
        avframe = nullptr;
    }

    if (out_fp)
    {
        fclose(out_fp);
        out_fp = nullptr;
    }

    if (encoder_ctx)
    {
        avcodec_free_context(&encoder_ctx);
        encoder_ctx = nullptr;
    }

    if (in_fp)
    {
        fclose(in_fp);
        in_fp = nullptr;
    }
}

performance


网站公告

今日签到

点亮在社区的每一天
去签到