FFmpeg編解碼常用函式ffmpeg av_parser_parse2()函式
主要是通過av_parser_parse2拿到AVPaket資料,跟av_read_frame類似。
輸入必須是隻包含視訊編碼資料“裸流”(例如H.264、HEVC碼流檔案),而不能是包含封裝格式的媒體資料(例如AVI、MKV、MP4)。
av_parser_init():初始化AVCodecParserContext。其引數是codec_id,所以同時只能解析一種
AVCodecParser用於解析輸入的資料流並把它們分成一幀一幀的壓縮編碼資料。比較形象的說法就是把長長的一段連續的資料“切割”成一段段的資料。核心函式是av_parser_parse2():
av_parser_parse2():解析資料獲得一個Packet, 從輸入的資料流中分離出一幀一幀的壓縮編碼資料。
/**
* Parse a packet.
*
* @param s parser context.
* @param avctx codec context.
* @param poutbuf set to pointer to parsed buffer or NULL if not yet finished.
* @param poutbuf_size set to size of parsed buffer or zero if not yet finished.
* @param buf input buffer.
* @param buf_size input length, to signal EOF, this should be 0 (so that the last frame can be output).
* @param pts input presentation timestamp.
* @param dts input decoding timestamp.
* @param pos input byte position in stream.
* @return the number of bytes of the input bitstream used.
*
* Example:
* @code
* while(in_len){
* len = av_parser_parse2(myparser, AVCodecContext, &data, &size,
* in_data, in_len,
* pts, dts, pos);
* in_data += len;
* in_len -= len;
*
* if(size)
* decode_frame(data, size);
* }
* @endcode
*/
int av_parser_parse2(AVCodecParserContext *s,
AVCodecContext *avctx,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size,
int64_t pts, int64_t dts,
int64_t pos);
第一個引數:
eg:
AVCodecParserContext *parser = NULL;
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
/* the codec gives us the frame size, in samples */
parser = av_parser_init(c->codec_id);
parser->flags |= PARSER_FLAG_ONCE;//在開啟解碼器後初始化parase
另一種用法:
AVStream *st = s->streams[stream_index];
len = av_parser_parse2(st->parser, st->codec,
&out_pkt.data, &out_pkt.size, data, size,
pkt->pts, pkt->dts, pkt->pos);
第二個引數:正常的AVCodecContext
第三個引數:初始化後的avpkt的avpkt.data
第四個引數:初始化後的avpkt的avpkt.size
第五個引數:一次接收的資料包
第六個引數:本次接收資料包的長度
第七個引數:pts,沒有的話,可以在聲明後直接用int pts,單單h264的話直接掛上pts即可
第八個引數:dts,同上
第九個引數:接收資料
其中poutbuf指向解析後輸出的壓縮編碼資料幀,buf指向輸入的壓縮編碼資料。如果函式執行完後輸出資料為空(poutbuf_size為0),則代表解析還沒有完成,還需要再次呼叫av_parser_parse2()解析一部分資料才可以得到解析後的資料幀。當函式執行完後輸出資料不為空的時候,代表解析完成,可以將poutbuf中的這幀資料取出來做後續處理。
avformat_open_input()會呼叫avformat_new_stream()建立AVStream
avformat_new_stream()中又會呼叫avcodec_alloc_context3()建立AVCodecContext
av_read_frame():獲取媒體的一幀壓縮編碼資料。其中呼叫了av_parser_parse2()。
“純淨”的解碼器中,通過avcodec_decode_video2()成功解碼第一幀之後,才能獲取到寬高等資訊
解析出來的資料,可通過下面的方法判斷幀型別:
AVCodecParserContext->pict_type :AV_PICTURE_TYPE_I,AV_PICTURE_TYPE_P