将单个像素值从RGB转换为YUV420并保存帧 - C ++

时间:2014-03-24 17:25:33

标签: c++ c ffmpeg video-encoding libavcodec

我使用FFmpeg库已经使用RGB-> YUV420转换了一段时间。已经尝试了sws_scale功能,但效果不佳。现在,我决定使用颜色空间转换公式单独转换每个像素。所以,下面的代码可以让我获得几帧,并允许我访问每个像素的各个R,G,B值:

// Read frames and save first five frames to disk
    i=0;
    while((av_read_frame(pFormatCtx, &packet)>=0) && (i<5)) 
    {
        // Is this a packet from the video stream?
        if(packet.stream_index==videoStreamIdx) 
        {   
            /// Decode video frame            
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

            // Did we get a video frame?
            if(frameFinished) 
            {
                i++;
                sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data,
                          pFrame->linesize, 0, pCodecCtx->height,
                          pFrameRGB->data, pFrameRGB->linesize);

                int x, y, R, G, B;
                uint8_t *p = pFrameRGB->data[0];
                for(y = 0; y < h; y++)
                {  
                    for(x = 0; x < w; x++) 
                    {
                        R = *p++;
                        G = *p++;
                        B = *p++;
                        printf(" %d-%d-%d ",R,G,B);
                    }
                }

                SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
            }
        }

        // Free the packet that was allocated by av_read_frame
        av_free_packet(&packet);
    }

我读online要转换RGB-&gt; YUV420,反之亦然,首先应转换为YUV444格式。因此,它类似于:RGB-&gt; YUV444-&gt; YUV420。我如何在C ++中实现它?

此外,这是上面使用的SaveFrame()函数。我想这也需要改变一点,因为YUV420以不同的方式存储数据。如何处理?

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
    FILE *pFile;
    char szFilename[32];
    int  y;

    // Open file
    sprintf(szFilename, "frame%d.ppm", iFrame);
    pFile=fopen(szFilename, "wb");
    if(pFile==NULL)
        return;

    // Write header
    fprintf(pFile, "P6\n%d %d\n255\n", width, height);

    // Write pixel data
    for(y=0; y<height; y++)
        fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);

    // Close file
    fclose(pFile);
}

有人可以建议吗?非常感谢!!!

1 个答案:

答案 0 :(得分:0)

void SaveFrameYUV420P(AVFrame *pFrame, int width, int height, int iFrame)
{
    FILE *pFile;
    char szFilename[32];
    int  y;

    // Open file
    sprintf(szFilename, "frame%d.yuv", iFrame);
    pFile=fopen(szFilename, "wb");
    if(pFile==NULL)
        return;

    // Write pixel data
    fwrite(pFrame->data[0], 1, width*height, pFile);
    fwrite(pFrame->data[1], 1, width*height/4, pFile);
    fwrite(pFrame->data[2], 1, width*height/4, pFile);

    // Close file
    fclose(pFile);
}

在Windows上,您可以使用irfanview查看以这种方式保存的帧。您将框架打开为RAW,24bpp格式,提供宽度和高度,并选中框&#34; yuv420&#34;。