static int h264_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; H264Context *h = avctx->priv_data; AVFrame *pict = data; int buf_index = 0; int ret; const uint8_t *new_extradata; int new_extradata_size; h->flags = avctx->flags; h->setup_finished = 0; /* end of stream, output what is still in the buffers */ out: if (buf_size == 0) { H264Picture *out; int i, out_idx; h->cur_pic_ptr = NULL; // FIXME factorize this with the output code below out = h->delayed_pic[0]; out_idx = 0; for (i = 1; h->delayed_pic[i] && !h->delayed_pic[i]->f->key_frame && !h->delayed_pic[i]->mmco_reset; i++) if (h->delayed_pic[i]->poc < out->poc) { out = h->delayed_pic[i]; out_idx = i; } for (i = out_idx; h->delayed_pic[i]; i++) h->delayed_pic[i] = h->delayed_pic[i + 1]; if (out) { ret = output_frame(h, pict, out->f); if (ret < 0) return ret; *got_frame = 1; } return buf_index; } new_extradata_size = 0; new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &new_extradata_size); if (new_extradata_size > 0 && new_extradata) { ret = ff_h264_decode_extradata(new_extradata, new_extradata_size, &h->ps, &h->is_avc, &h->nal_length_size, avctx->err_recognition, avctx); if (ret < 0) return ret; } buf_index = decode_nal_units(h, buf, buf_size); if (buf_index < 0) return AVERROR_INVALIDDATA; if (!h->cur_pic_ptr && h->nal_unit_type == NAL_END_SEQUENCE) { buf_size = 0; goto out; } if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS) && !h->cur_pic_ptr) { if (avctx->skip_frame >= AVDISCARD_NONREF) return 0; av_log(avctx, AV_LOG_ERROR, "no frame!\n"); return AVERROR_INVALIDDATA; } if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS) || (h->mb_y >= h->mb_height && h->mb_height)) { if (avctx->flags2 & AV_CODEC_FLAG2_CHUNKS) decode_postinit(h, 1); ff_h264_field_end(h, &h->slice_ctx[0], 0); *got_frame = 0; if (h->next_output_pic && ((avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) || h->next_output_pic->recovered)) { if (!h->next_output_pic->recovered) h->next_output_pic->f->flags |= AV_FRAME_FLAG_CORRUPT; ret = output_frame(h, pict, h->next_output_pic->f); if (ret < 0) return ret; *got_frame = 1; } } assert(pict->buf[0] || !*got_frame); return get_consumed_bytes(buf_index, buf_size); }