前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >3.AVPacket使用

3.AVPacket使用

作者头像
诺谦
发布2020-07-06 16:08:01
9890
发布2020-07-06 16:08:01
举报
文章被收录于专栏:Linux驱动Linux驱动

结构体如下:

代码语言:javascript
复制
typedef struct AVPacket{
/**
* A reference to the reference-counted buffer where the packet data is
* stored.
* May be NULL, then the packet data is not reference-counted.
*/
AVBufferRef *buf;    
//用来管理data指针引用的数据缓存,通过av_packet_ref() 和 av_packet_unref()
//来使buf->buffer->refcount成员引用计数+-,如果引用计数为0,则释放buffer. 
/**
* Presentation timestamp in AVStream->time_base units; the time at which
* the decompressed packet will be presented to the user.
* Can be AV_NOPTS_VALUE if it is not stored in the file.
* pts MUST be larger or equal to dts as presentation cannot happen before
* decompression, unless one wants to view hex dumps. Some formats misuse
* the terms dts and pts/cts to mean something different. Such timestamps
* must be converted to true pts/dts before they are stored in AVPacket.
*/
int64_t pts;    
//显示时间戳,需要所属媒体流AVStream的time_base时基来换算出当前显示的标准时间(时分秒)
//比如dpts = av_q2d(AVStream->time_base) * AVPacket->pts;

int64_t dts;       //解码时间戳,需要所属媒体流AVStream的time_base时基来换算出当前显示的标准时间(时分秒)
uint8_t *data;    //压缩编码的数据。
int size;     //data的大小
int stream_index;    //标识该AVPacket所属的视频/音频流

int flags;    //标识,结合AV_PKT_FLAG使用,比如:
//#define AV_PKT_FLAG_KEY 0x0001 //关键帧
//#define AV_PKT_FLAG_CORRUPT 0x0002 //损坏的数据
//#define AV_PKT_FLAG_DISCARD 0x0004 /丢弃的数据

/**
* Additional packet data that can be provided by the container.
* Packet can contain several types of side information.
*/
AVPacketSideData *side_data;    //容器提供的一些附加数据
int side_data_elems;         //边缘数据元数个数

/**
* Duration of this packet in AVStream->time_base units, 0 if unknown.
* Equals next_pts - this_pts in presentation order.
*/
int64_t duration;    //数据的时长,需要所属媒体流AVStream的time_base时基来换算出当前的标准时间,未知则值为默认值0

int64_t pos;        //数据在流媒体中的位置,未知则值为默认值-1

}AVPacket;

AVPacket常用函数如下:

代码语言:javascript
复制
AVPacket *av_packet_alloc(void)
{
   AVPacket *pkt = av_mallocz(sizeof(AVPacket));
   if (!pkt)
    return pkt;

   av_packet_unref(pkt);

   return pkt;
}

创建一个AVPacket的实例,但该函数并不会为数据分配空间,其指向数据域的指针为NULL。

代码语言:javascript
复制
void av_packet_free(AVPacket **pkt)
{
  if (!pkt || !*pkt)
    return;

  av_packet_unref(*pkt);
  av_freep(pkt);
}

首先将AVPacket->buf->buffer->refcount成员减1(数据域的引用技术减为0时会自动释放),然后再释放为AVPacket分配的空间。

代码语言:javascript
复制
int av_packet_ref(AVPacket *dst, const AVPacket *src)
{
  int ret;

  ret = av_packet_copy_props(dst, src); //复制部分成员(比如:pts,dts,pos,duration,side_data)到dst
  if (ret < 0)
    return ret;

  if (!src->buf) { //如果src->buf为空,则为dst新分配一个数据域,并将src->data复制到dst->buf->data
    ret = packet_alloc(&dst->buf, src->size);
  if (ret < 0)
   goto fail;
  av_assert1(!src->size || src->data);
  if (src->size)
    memcpy(dst->buf->data, src->data, src->size);

  dst->data = dst->buf->data;
 } else { //不为空,则调用av_buffer_ref()来使引用+1,并将dst->buf指向src->buf,
  dst->buf = av_buffer_ref(src->buf);
  if (!dst->buf) {
  ret = AVERROR(ENOMEM);
  goto fail;
 }
  dst->data = src->data;    //然后将src->data复制到dst->data中
 }

  dst->size = src->size;

  return 0;
  fail:
    av_packet_free_side_data(dst);
  return ret;
}

av_packet_ref根据src来创建一个新的AVPacket

代码语言:javascript
复制
void av_packet_unref(AVPacket *pkt)
{
  av_packet_free_side_data(pkt);
  av_buffer_unref(&pkt->buf);
  av_init_packet(pkt);
  pkt->data = NULL;
  pkt->size = 0;
}

将AVPacket->buf->buffer->refcount成员减1(数据域的引用技术减为0时会自动释放),替代了旧api(av_free_packet)

AVPacket解码示例:

代码语言:javascript
复制
AVPacket *packet = av_packet_alloc(); // 创建一个packet

while(av_read_frame(pFormatCtx,packet))
{
  if(packet->stream_index == audio_index)
  {
    ...
  }
  else if(packet->stream_index == video_index)
  {
   ...
  }

  av_packet_unref(packet); // 也可以使用旧api:av_free_packet
}
av_packet_free(packet);    //释放packet,如果还想使用,则需要重新alloc
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档