16.try_decode_frame
接着笔记四 分析这个API
//这个API很简单,根据codec_type调用相应的API 解码
static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,
AVDictionary **options)
{
...
//如果decodec已经open,跳过.根据前面分析,这儿会跳过
...
//根据codec type,调用相应的API
while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
ret >= 0 &&
(!has_codec_parameters(st, NULL) || !has_decode_delay_been_guessed(st) ||
(!st->codec_info_nb_frames &&
st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) {
got_picture = 0;
switch (st->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
//接下来介绍
ret = avcodec_decode_video2(st->codec, frame,
&got_picture, &pkt);
break;
case AVMEDIA_TYPE_AUDIO:
ret = avcodec_decode_audio4(st->codec, frame, &got_picture, &pkt);
break;
case AVMEDIA_TYPE_SUBTITLE:
ret = avcodec_decode_subtitle2(st->codec, &subtitle,
&got_picture, &pkt);
ret = pkt.size;
break;
default:
break;
}
}
...
}
int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
int *got_picture_ptr,
const AVPacket *avpkt)
{
...
//将picture 清一下
av_frame_unref(picture);
if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) {
int did_split = av_packet_split_side_data(&tmp);
ret = apply_param_change(avctx, &tmp);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
if (avctx->err_recognition & AV_EF_EXPLODE)
goto fail;
}
avctx->internal->pkt = &tmp;
//是否用多线程
/*
以hevc为例:
AVCodec ff_hevc_decoder = {
...
.decode = hevc_decode_frame,
...
};
*/
if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
&tmp);
else {
//调用codec->decoder去解码
ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
&tmp);
...
}
//处理side_data
add_metadata_from_side_data(avctx, picture);
...
}
//decode_nal_units 这个是parse nal_units,不是nal_unit
static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output,
AVPacket *avpkt)
{
...
ret = decode_nal_units(s, avpkt->data, avpkt->size);
...
if (s->output_frame->buf[0]) {
//将s->output_frame 拷贝到data (AVFrame type)
av_frame_move_ref(data, s->output_frame);
*got_output = 1;
}
return avpkt->size;
}
static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
{
while (length >= 4) {
HEVCNAL *nal;
int extract_length = 0;
if (s->is_nalff) {
int i;
//如果文件头部包含一些codec 信息(mkv 文件,存放在track/codecprivate)
//是不需要找start code的,data的头部就保存着nalu长度.
for (i = 0; i < s->nal_length_size; i++)
extract_length = (extract_length << 8) | buf[i];
buf += s->nal_length_size;
length -= s->nal_length_size;
if (extract_length > length) {
av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit size.\n");
ret = AVERROR_INVALIDDATA;
goto fail;
}
} else {
/* search start code */
//找start code,找到之后,跳出这个while
while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) {
++buf;
--length;
if (length < 4) {
av_log(s->avctx, AV_LOG_ERROR, "No start code is found.\n");
ret = AVERROR_INVALIDDATA;
goto fail;
}
}
buf += 3;
length -= 3;
}
if (!s->is_nalff)
extract_length = length;
if (s->nals_allocated < s->nb_nals + 1) {
int new_size = s->nals_allocated + 1;
HEVCNAL *tmp = av_realloc_array(s->nals, new_size, sizeof(*tmp));
if (!tmp) {
ret = AVERROR(ENOMEM);
goto fail;
}
s->nals = tmp;
memset(s->nals + s->nals_allocated, 0,
(new_size - s->nals_allocated) * sizeof(*tmp));
av_reallocp_array(&s->skipped_bytes_nal, new_size, sizeof(*s->skipped_bytes_nal));
av_reallocp_array(&s->skipped_bytes_pos_size_nal, new_size, sizeof(*s->skipped_bytes_pos_size_nal));
av_reallocp_array(&s->skipped_bytes_pos_nal, new_size, sizeof(*s->skipped_bytes_pos_nal));
s->skipped_bytes_pos_size_nal[s->nals_allocated] = 1024; // initial buffer size
s->skipped_bytes_pos_nal[s->nals_allocated] = av_malloc_array(s->skipped_bytes_pos_size_nal[s->nals_allocated], sizeof(*s->skipped_bytes_pos));
s->nals_allocated = new_size;
}
s->skipped_bytes_pos_size = s->skipped_bytes_pos_size_nal[s->nb_nals];
s->skipped_bytes_pos = s->skipped_bytes_pos_nal[s->nb_nals];
nal = &s->nals[s->nb_nals];
consumed = ff_hevc_extract_rbsp(s, buf, extract_length, nal);
s->skipped_bytes_nal[s->nb_nals] = s->skipped_bytes;
s->skipped_bytes_pos_size_nal[s->nb_nals] = s->skipped_bytes_pos_size;
s->skipped_bytes_pos_nal[s->nb_nals++] = s->skipped_bytes_pos;
if (consumed < 0) {
ret = consumed;
goto fail;
}
ret = init_get_bits8(&s->HEVClc->gb, nal->data, nal->size);
if (ret < 0)
goto fail;
hls_nal_unit(s);
if (s->nal_unit_type == NAL_EOB_NUT ||
s->nal_unit_type == NAL_EOS_NUT)
s->eos = 1;
buf += consumed;
length -= consumed;
}
/* parse the NAL units */
for (i = 0; i < s->nb_nals; i++) {
...
//parse 这个packet中的每一个nal
ret = decode_nal_unit(s, s->nals[i].data, s->nals[i].size);
...
}
...
}
//根据nal type,去真正的decoder 每一个nal,这块根据hevc spec进行decoder
//我对这块也不是很懂,以后有空再深入研究
static int decode_nal_unit(HEVCContext *s, const uint8_t *nal, int length)
{
HEVCLocalContext *lc = s->HEVClc;
GetBitContext *gb = &lc->gb;
int ctb_addr_ts, ret;
ret = init_get_bits8(gb, nal, length);
if (ret < 0)
return ret;
ret = hls_nal_unit(s);
if (ret < 0) {
av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n",
s->nal_unit_type);
goto fail;
} else if (!ret)
return 0;
switch (s->nal_unit_type) {
case NAL_VPS:
ret = ff_hevc_decode_nal_vps(s);
if (ret < 0)
goto fail;
break;
case NAL_SPS:
ret = ff_hevc_decode_nal_sps(s);
if (ret < 0)
goto fail;
break;
case NAL_PPS:
ret = ff_hevc_decode_nal_pps(s);
if (ret < 0)
goto fail;
break;
case NAL_SEI_PREFIX:
case NAL_SEI_SUFFIX:
ret = ff_hevc_decode_nal_sei(s);
if (ret < 0)
goto fail;
break;
case NAL_TRAIL_R:
case NAL_TRAIL_N:
case NAL_TSA_N:
case NAL_TSA_R:
case NAL_STSA_N:
case NAL_STSA_R:
case NAL_BLA_W_LP:
case NAL_BLA_W_RADL:
case NAL_BLA_N_LP:
case NAL_IDR_W_RADL:
case NAL_IDR_N_LP:
case NAL_CRA_NUT:
case NAL_RADL_N:
case NAL_RADL_R:
case NAL_RASL_N:
case NAL_RASL_R:
ret = hls_slice_header(s);
if (ret < 0)
return ret;
if (s->max_ra == INT_MAX) {
if (s->nal_unit_type == NAL_CRA_NUT || IS_BLA(s)) {
s->max_ra = s->poc;
} else {
if (IS_IDR(s))
s->max_ra = INT_MIN;
}
}
if ((s->nal_unit_type == NAL_RASL_R || s->nal_unit_type == NAL_RASL_N) &&
s->poc <= s->max_ra) {
s->is_decoded = 0;
break;
} else {
if (s->nal_unit_type == NAL_RASL_R && s->poc > s->max_ra)
s->max_ra = INT_MIN;
}
if (s->sh.first_slice_in_pic_flag) {
ret = hevc_frame_start(s);
if (ret < 0)
return ret;
} else if (!s->ref) {
av_log(s->avctx, AV_LOG_ERROR, "First slice in a frame missing.\n");
goto fail;
}
if (s->nal_unit_type != s->first_nal_type) {
av_log(s->avctx, AV_LOG_ERROR,
"Non-matching NAL types of the VCL NALUs: %d %d\n",
s->first_nal_type, s->nal_unit_type);
return AVERROR_INVALIDDATA;
}
if (!s->sh.dependent_slice_segment_flag &&
s->sh.slice_type != I_SLICE) {
ret = ff_hevc_slice_rpl(s);
if (ret < 0) {
av_log(s->avctx, AV_LOG_WARNING,
"Error constructing the reference lists for the current slice.\n");
goto fail;
}
}
if (s->threads_number > 1 && s->sh.num_entry_point_offsets > 0)
ctb_addr_ts = hls_slice_data_wpp(s, nal, length);
else
ctb_addr_ts = hls_slice_data(s);
if (ctb_addr_ts >= (s->sps->ctb_width * s->sps->ctb_height)) {
s->is_decoded = 1;
}
if (ctb_addr_ts < 0) {
ret = ctb_addr_ts;
goto fail;
}
break;
case NAL_EOS_NUT:
case NAL_EOB_NUT:
s->seq_decode = (s->seq_decode + 1) & 0xff;
s->max_ra = INT_MAX;
break;
case NAL_AUD:
case NAL_FD_NUT:
break;
default:
av_log(s->avctx, AV_LOG_INFO,
"Skipping NAL unit %d\n", s->nal_unit_type);
}
return 0;
fail:
if (s->avctx->err_recognition & AV_EF_EXPLODE)
return ret;
return 0;
}