FFmpeg之AVPacket

来源:互联网 发布:轧机压下数据传感 编辑:程序博客网 时间:2024/06/03 17:09

花满楼原创


AVPacket,是压缩数据的结构体(解码前或编码后的结构体)。

本文介绍FFmepg中常见结构AVPacekt,尽量用具体值来理解。

整个用于调试的代码可以这样写:

#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"void show_frame(const char* filepath) {    av_register_all();    av_log_set_level(AV_LOG_DEBUG);    AVFormatContext* formatContext = avformat_alloc_context();    int status = 0;    int success = 0;    int videostreamidx = -1;    AVCodecContext* codecContext = NULL;    status = avformat_open_input(&formatContext, filepath, NULL, NULL);    if (status == 0) {        status = avformat_find_stream_info(formatContext, NULL);        if (status >= 0) {            for (int i = 0; i < formatContext->nb_streams; i ++) {                if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {                    videostreamidx = i;                    break;                }            }            if (videostreamidx > -1) {                AVStream* avstream = formatContext->streams[videostreamidx];                codecContext = avstream->codec;                AVCodec* codec = avcodec_find_decoder(codecContext->codec_id);                if (codec) {                    status = avcodec_open2(codecContext, codec, NULL);                    if (status == 0) {                        success = 1;                    }                }            }        }        else {            av_log(NULL, AV_LOG_DEBUG, "avformat_find_stream_info error\n");        }        if (success) {            av_dump_format(formatContext, 0, filepath, 0);            int gotframe = 0;            AVFrame* frame = av_frame_alloc();            int decodelen = 0;            int limitcount = 10;            int pcindex = 0;            while (pcindex < limitcount) {                AVPacket packet;                av_init_packet( &packet );                status = av_read_frame(formatContext, &packet);                if (status < 0) {                    if (status == AVERROR_EOF) {                        av_log(NULL, AV_LOG_DEBUG, "read end for file\n");                    }                    else {                        av_log(NULL, AV_LOG_DEBUG, "av_read_frame error\n");                    }                    av_packet_unref(&packet);                    break;                  }                else {                    if (packet.stream_index == videostreamidx) {                        decodelen = avcodec_decode_video2(codecContext, frame, &gotframe, &packet);                        if (decodelen > 0 && gotframe) {                            av_log(NULL, AV_LOG_DEBUG, "got one avframe, pcindex=%d\n", pcindex);                        }                       }                }                 av_packet_unref(&packet);                pcindex ++;            }            av_frame_free(&frame);        }        avformat_close_input(&formatContext);    }    avformat_free_context(formatContext);}int main(int argc, char *argv[]){    show_frame("moments.mp4");    return 0;}

av_read_frame函数可以取得一个AVPacket,所以在调用这个函数的地方下个断点,看一下AVPacet长什么样子。

编译脚本还是沿用之前介绍的makefile或直接用gcc来编译。

在没有调用av_read_frame前,AVPacket中的变量值:
没有调用av_read_frame的avpacket

调用av_read_frame后,AVPacket中的变量:
avpacket1

再一次av_read_frame后:
avpacket2

av_read_frame后,AVPacket也可能没有数据:
avpacket没有数据的情况

AVPacket是压缩数据,一个AVPacket,对于视频最多一帧(NALU),但对于音频就可能多帧。

AVPacket中的变量含义:

pts/dts,显示/解码时间戵,以packet所在的流的time_base为单位。stream_index,所在流的索引。data,avpacket拥有的数据。size,avpacket的数据长度。duration,avpacket的时长,同样以time_base为单位。

AVPacket结构,在libavcodec/avcodec.h中定义。