http://www.cnblogs.com/my_life/articles/6279070.html
FFMPEG使用AVPacket来暂存解复用之后、解码之前的媒体数据(一个音/视频帧、一个字幕包等)及附加信息(解码时间戳、显示时间戳、时长等)。其中:
-
dts表示解码时间戳,pts表示显示时间戳,它们的单位是所属媒体流的时间基准。
-
stream_index给出所属媒体流的索引;
-
data为数据缓冲区指针,size为长度;
-
duration为数据的时长,也是以所属媒体流的时间基准为单位;
-
pos表示该数据在媒体流中的字节偏移量;
-
destruct为用于释放数据缓冲区的函数指针;
-
flags为标志域,其中,最低为置1表示该数据是一个关键帧。
AVPacket结构本身只是个容器,它使用data成员引用实际的数据缓冲区。这个缓冲区通常是由av_new_packet创建的,但也可能由 FFMPEG的API创建(如av_read_frame)。当某个AVPacket结构的数据缓冲区不再被使用时,要需要通过调用 av_free_packet释放。
av_free_packet调用的是结构体本身的destruct函数,它的值有两种情 况:
1)av_destruct_packet_nofree或0;
2)av_destruct_packet,
其中,情况1)仅仅是将data和 size的值清0而已,情况2)才会真正地释放缓冲区。
FFMPEG内部使用AVPacket结构建立缓冲区装载数据,同时提供destruct函数,如果FFMPEG打算自己维护缓冲区,则将 destruct设为av_destruct_packet_nofree,用户调用av_free_packet清理缓冲区时并不能够将其释放;
如果 FFMPEG打算将该缓冲区彻底交给调用者,则将destruct设为av_destruct_packet,表示它能够被释放。
安全起见,如果用户希望 自由地使用一个FFMPEG内部创建的AVPacket结构,最好调用av_dup_packet进行缓冲区的克隆,将其转化为缓冲区能够被释放的 AVPacket,以免对缓冲区的不当占用造成异常错误。
av_dup_packet会为destruct指针为 av_destruct_packet_nofree的AVPacket新建一个缓冲区,然后将原缓冲区的数据拷贝至新缓冲区,置data的值为新缓冲区 的地址,同时设destruct指针为av_destruct_packet。
AVPacket 的data 在内存中buffer有两种情况:
1)由av_malloc申请的独立的buffer(unshared buffer);
2)是其他AVPacket或者其他reuseable 内存的一部分(shared buffer); 此时data只是一个指针指向。
av_dup_packet, 通过调用 av_malloc、memcpy、memset等函数, 将原本指针指向的共享内存shared buffer 的AVPacket duplicate(复制)到独立的buffer中,并且修改AVPacket的析构函数指针av_destruct_pkt。
av_dup_packet源码:
00092 int av_dup_packet(AVPacket *pkt)
00093 {
00094 if (((pkt->destruct == av_destruct_packet_nofree) || (pkt->destruct == NULL)) && pkt->data) {
00095 uint8_t *data; //定义数据栈上的数据指针
00096 /* We duplicate the packet and don't forget to add the padding again. */
00097 if((unsigned)pkt->size > (unsigned)pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)
00098 return AVERROR(ENOMEM);
00099 data = av_malloc(pkt->size + FF_INPUT_BUFFER_PADDING_SIZE); //申请内存
00100 if (!data) {
00101 return AVERROR(ENOMEM);
00102 }
00103 memcpy(data, pkt->data, pkt->size); //把共享的内存拷过去
00104 memset(data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00105 pkt->data = data; // 重新设置pkt->data终于有自己的独立内存了,不用共享别的AVPacket的内存
00106 pkt->destruct = av_destruct_packet; //设置析构函数指针
00107 }
00108 return 0;
00109 }
浙公网安备 33010602011771号