FFmpeg - MJPEG解码提供不一致的值

时间:2016-12-27 08:41:54

标签: ffmpeg mjpeg libavcodec libav

我有一组JPEG帧,我正在将它复用到avi中,这给了我一个mjpeg视频。这是我在控制台上运行的命令:

ffmpeg -y -start_number 0 -i %06d.JPEG -codec copy vid.avi

当我尝试使用ffmpeg C api对视频进行解复用时,我会得到值略有不同的帧。解复用代码看起来像这样:

AVFormatContext* fmt_ctx = NULL;
AVCodecContext* cdc_ctx = NULL;
AVCodec* vid_cdc = NULL;
int ret;
unsigned int height, width;

....
// read_nframes is the number of frames to read
output_arr = new unsigned char [height * width * 3 * 
                                sizeof(unsigned char) * read_nframes];

avcodec_open2(cdc_ctx, vid_cdc, NULL);

int num_bytes;
uint8_t* buffer = NULL;
const AVPixelFormat out_format = AV_PIX_FMT_RGB24;

num_bytes = av_image_get_buffer_size(out_format, width, height, 1);
buffer = (uint8_t*)av_malloc(num_bytes * sizeof(uint8_t));

AVFrame* vid_frame = NULL;
vid_frame = av_frame_alloc();
AVFrame* conv_frame = NULL;
conv_frame = av_frame_alloc();

av_image_fill_arrays(conv_frame->data, conv_frame->linesize, buffer, 
                     out_format, width, height, 1);

struct SwsContext *sws_ctx = NULL;
sws_ctx = sws_getContext(width, height, cdc_ctx->pix_fmt,
                         width, height, out_format,
                         SWS_BILINEAR, NULL,NULL,NULL);

int frame_num = 0;
AVPacket vid_pckt;
while (av_read_frame(fmt_ctx, &vid_pckt) >=0) {
    ret = avcodec_send_packet(cdc_ctx, &vid_pckt);
    if (ret < 0)
        break;

    ret = avcodec_receive_frame(cdc_ctx, vid_frame);
    if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
        break;
    if (ret >= 0) {
        // convert image from native format to planar GBR
        sws_scale(sws_ctx, vid_frame->data, 
                  vid_frame->linesize, 0, vid_frame->height, 
                  conv_frame->data, conv_frame->linesize);

        unsigned char* r_ptr = output_arr + 
            (height * width * sizeof(unsigned char) * 3 * frame_num);
        unsigned char* g_ptr = r_ptr + (height * width * sizeof(unsigned char));
        unsigned char* b_ptr = g_ptr + (height * width * sizeof(unsigned char));
        unsigned int pxl_i = 0;

        for (unsigned int r = 0; r < height; ++r) {
            uint8_t* avframe_r = conv_frame->data[0] + r*conv_frame->linesize[0];
            for (unsigned int c = 0; c < width; ++c) {
                r_ptr[pxl_i] = avframe_r[0];
                g_ptr[pxl_i]   = avframe_r[1];
                b_ptr[pxl_i]   = avframe_r[2];
                avframe_r += 3;
                ++pxl_i;
            }
        }

        ++frame_num;

        if (frame_num >= read_nframes)
            break;
    }
}

...

根据我的经验,大约三分之二的像素值是不同的,每个都是+ -1(在[0,255]的范围内)。我想知道是因为FFmpeg用于读取JPEG帧的一些解码方案?我尝试编码和解码png帧,它工作得非常好。我确信这与libav解码过程有关,因为MD5值在图像和视频之间是一致的:

ffmpeg -i %06d.JPEG -f framemd5 -
ffmpeg -i vid.avi -f framemd5 -

简而言之,我的目标是为每个JPEG帧提供相同的像素值,就像我直接读取JPEG图像一样。这是我使用的stand-alone bitbucket code。它包括用于构建代码的cmake文件,以及带有转换后的avi文件的几个jpeg框架来测试此问题。 (给'--filetype png'测试png解码)。

0 个答案:

没有答案