如何从AVFrame::data【0】里获取RGB24数据和YUYV422数据

如何从AVFrame::data[0]里获取RGB24数据,又如何从中获取YUYV422数据

  • 提出问题:
我用img_convert转换了解码后的图象为RGB24,确保转换是正确的,取出数据来播放还是不正常。
我又转为YUYV422,还是不正常。 
反正就是数据没取对。
我是从AVFrame::data[0]直接把数据Copy过来显示,
要么图象只显示到上半窗口,要么重复了几个播放图象,怎么弄都不正确
请问,怎么取这两种格式的图象数据啊?
    • 解答问题
从AVFrame::data[0]里获取RGB24 或者 YUYV422,或者 UYVY422 都只是从data[0]里获取就可以了,忽略data[1], data[2], data[3];
其次,我由于使用了img_convert进行了到上述目标格式的转换,但是却为转换用的AVPicture变量,调用avpicture_alloc指定的目标格式还是
PIX_FMT_YUV420P,也就是说,分配的目标格式和转换的目标格式不匹配对应。
因此,可能一方面导致AVPicture变量中的目标格式不正确,还导致其分配的缓冲区太小,从而导致后来取数据不正确,结果图象被隔行采样,实际视频高少了一
半。
其实只要分配和转换不发生任何问题,就只需要从AVFrame::data[0]直接Copy数据即可,而Copy数据的长度,即是一帧BMP图片的大小。
唯有RGB24,这样一次Copy,显示后,图象倒置,需要进行一行一行Copy,才正确。
    • 相关解释
AVFrame::data[0] 和 AVPicture::data[0],众所周知,都是一样的意义。
换句话说结构体AVFrame 和 结构体AVPicture表示图象数据的字段部分完全相同,而AVFrame只是比AVPicture多了些字段。
因此,上述问题及解答中,说“从AVFrame::data[0] 获取数据”也表达“从AVPicture::data[0]获取数据 ”同等的意思。
    • 相关代码
这里同时给出FFMPEG默认的解码输出格式PIX_FMT_YUV420P,获取解码数据的方式
int i, j, nshift, nBufPtr = 0;
uint8_t*   yuv_factor;
for( i=0; i<3; i++ )
{
     nshift = (i == 0 ? 0:1);
    yuv_factor = m_pAVFrame->data;
    for( j = 0; j < (m_pContext->height >> nshift); j++ )
   {
       memcpy( (char*)m_pOutBuff + nBufPtr, yuv_factor, (m_pContext->width >> nshift) );
       yuv_factor += m_pAVFrame->linesize;
       nBufPtr    += (m_pContext->width >> nshift);
   }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Android中从MediaCodec读取数据并将其存储到AVFrame中,需要进行以下步骤: 1. 初始化AVFrame 在使用AVFrame之前,需要先初始化它。可以使用下面的代码初始化AVFrame: ``` AVFrame *frame = av_frame_alloc(); frame->format = AV_PIX_FMT_YUV420P; // 设置像素格式 frame->width = width; // 设置帧宽度 frame->height = height; // 设置帧高度 ``` 2. 从MediaCodec读取数据 可以使用MediaCodec的dequeueOutputBuffer()方法从MediaCodec读取输出缓冲区。以下是一个示例代码: ``` MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_US); while (outputBufferIndex >= 0) { ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex); if (outputBuffer != null) { // 将数据存储到AVFrame中 // ... // 释放输出缓冲区 mediaCodec.releaseOutputBuffer(outputBufferIndex, false); } outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_US); } ``` 在从MediaCodec读取数据后,可以将数据存储到AVFrame中。以下是一个示例代码: ``` byte[] yuvData = new byte[width * height * 3 / 2]; outputBuffer.get(yuvData); // 将数据存储到AVFrame中 frame->data[0] = yuvData; // Y数据 frame->data[1] = yuvData + width * height; // U数据 frame->data[2] = yuvData + width * height * 5 / 4; // V数据 // 设置AVFrame的时间戳 frame->pts = bufferInfo.presentationTimeUs * AV_TIME_BASE / 1000000; ``` 在存储完数据后,需要释放MediaCodec的输出缓冲区。最后,我们可以在循环中继续读取数据,直到读取完所有数据。 需要注意的是,在从MediaCodec读取数据时,需要根据实际情况进行一些设置,例如超时时间和输出缓冲区的标志位等。另外,需要根据实际情况设置AVFrame的时间戳。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值