2016-02-27 44 views
1

我想获得一个帧的像素数据。我发现这个(原始版本是旧代码)并改变了一些东西。C++ videoplayer ffmpeg:获取像素数据?

我有这样的代码:

AVFormatContext *pFormatCtx; 
pFormatCtx = avformat_alloc_context(); 
// Open file 
if (int err = avformat_open_input(&pFormatCtx, file, NULL, 0) != 0) 
{ 
    exit(2); 
} 
// Get infromation about streams 
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) 
{ 
    exit(2); 
} 

// # video stream 
int videoStreamIndex = -1; 
AVCodecContext *pVideoCodecCtx; 
AVCodec *pVideoCodec; 
int res = 0; 
int width = 0; 
int height = 0; 
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) 
{ 
    if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
    { 
     videoStreamIndex = i; 
     pVideoCodecCtx = pFormatCtx->streams[i]->codec; 
     // Find decoder 
     pVideoCodec = avcodec_find_decoder(pVideoCodecCtx->codec_id); 
     if (pVideoCodec) 
     { 
      // Open decoder 
      res = !(avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL) < 0); 
      width = pVideoCodecCtx->coded_width; 
      height = pVideoCodecCtx->coded_height; 
     } 
     break; 
    } 
} 
// Frame width 
width = pFormatCtx->streams[videoStreamIndex]->codec->width; 
// Frame height 
height = pFormatCtx->streams[videoStreamIndex]->codec->height; 


AVPacket packet; 
int got_picture_ptr; 
AVPacket *avpkt; 
AVFrame * pOutFrame; 
pOutFrame = av_frame_alloc(); 
AVFrame * rgbOutFrame = av_frame_alloc(); 

if (!pOutFrame) { 
    fprintf(stderr, "Could not allocate video frame\n"); 
    exit(1); 
} 

while (av_read_frame(pFormatCtx, &packet) >= 0) 
{ 
    if (packet.stream_index == videoStreamIndex) 
    { 
     // Decode packeg to frame. 
     int videoFrameBytes = avcodec_decode_video2(pVideoCodecCtx, pOutFrame, 
      &got_picture_ptr, &packet); 

     // Create context 
     SwsContext* pImgConvertCtx = sws_getContext(pVideoCodecCtx->width, 
      pVideoCodecCtx->height, 
      pVideoCodecCtx->pix_fmt, 
      pVideoCodecCtx->width, pVideoCodecCtx->height, 
      AV_PIX_FMT_YUV420P, 
      SWS_BICUBIC, NULL, NULL, NULL); 
     // Convert frame 
     sws_scale(pImgConvertCtx, pOutFrame->data, pOutFrame->linesize, 
      width, height, rgbOutFrame->data, rgbOutFrame->linesize); 
    } 

} 

我知道,从SwsContextsws_scale代码是错误的,但我不知道,我在哪里可以找到我的帧的像素数据...(以及以何种格式它被存储)。

有人可以帮我吗?

回答

2

像素数据存储在数据字段中。

根据文档:

uint8_t * AVFrame ::数据[AV_NUM_DATA_POINTERS]

指针图象/信道平面。

查看here了解更多信息。

一般来说,你的代码有点误导性,而且有些问题。我可以指出一些缺点:

1)您不需要在每个传入视频数据包上创建新的SwsContext。只需在while周期之前创建一次。

2)其次,你有一个rgbOutFrame,但是对于缩放到YUV420像素格式创建SwsContext。它看起来很奇怪。

3)此外,avcodec_decode_video2被调用,但您从不检查返回值,也不检查got_picture_ptr标志。这种做法实际上是容易出错。

等等......

希望它会帮助你提高你的程序,并得到必要的结果。

+0

感谢您的快速回答,但我仍然有一些问题:什么是图片平面?我应该怎么做才能获得像素值? – 3DExtended

+0

我试图使用类似于frame-> data [0] [i]的值作为位置i的值,但它是一个uint8_t(我认为rgba)。但是当我使用它像rgba时,只有alpha值有一个不为零的值...请帮助:/ – 3DExtended

+0

@ 3DExtended尝试更改'sws_getContext'以转换为'rgb',而不是'yuv420' –