static int decode_new_packet(struct sh_audio *sh) { struct priv *priv = sh->context; AVCodecContext *avctx = priv->avctx; double pts = MP_NOPTS_VALUE; int insize; bool packet_already_used = priv->previous_data_left; struct demux_packet *mpkt = ds_get_packet2(sh->ds, priv->previous_data_left); unsigned char *start; if (!mpkt) { assert(!priv->previous_data_left); start = NULL; insize = 0; ds_parse(sh->ds, &start, &insize, pts, 0); if (insize <= 0) return -1; // error or EOF } else { assert(mpkt->len >= priv->previous_data_left); if (!priv->previous_data_left) { priv->previous_data_left = mpkt->len; pts = mpkt->pts; } insize = priv->previous_data_left; start = mpkt->buffer + mpkt->len - priv->previous_data_left; int consumed = ds_parse(sh->ds, &start, &insize, pts, 0); priv->previous_data_left -= consumed; priv->previous_data_left = FFMAX(priv->previous_data_left, 0); } AVPacket pkt; av_init_packet(&pkt); pkt.data = start; pkt.size = insize; if (mpkt && mpkt->avpacket) { pkt.side_data = mpkt->avpacket->side_data; pkt.side_data_elems = mpkt->avpacket->side_data_elems; } if (pts != MP_NOPTS_VALUE && !packet_already_used) { sh->pts = pts; sh->pts_bytes = 0; } int got_frame = 0; int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt); // LATM may need many packets to find mux info if (ret == AVERROR(EAGAIN)) return 0; if (ret < 0) { mp_msg(MSGT_DECAUDIO, MSGL_V, "lavc_audio: error\n"); return -1; } // The "insize >= ret" test is sanity check against decoder overreads if (!sh->parser && insize >= ret) priv->previous_data_left = insize - ret; if (!got_frame) return 0; int format_result = setup_format(sh); if (format_result < 0) return format_result; #ifdef CONFIG_LIBAVRESAMPLE if (priv->avr) { int ret; uint64_t needed_size = av_samples_get_buffer_size( NULL, priv->resample_channels, priv->avframe->nb_samples, priv->resample_fmt, 0); if (needed_size > priv->resample_buf_size) { priv->resample_buf = talloc_realloc(priv, priv->resample_buf, uint8_t, needed_size); priv->resample_buf_size = needed_size; } ret = avresample_convert(priv->avr, &priv->resample_buf, priv->resample_buf_size, priv->avframe->nb_samples, priv->avframe->extended_data, priv->avframe->linesize[0], priv->avframe->nb_samples); if (ret < 0) { uint8_t error[128]; av_strerror(ret, error, sizeof(error)); mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error during sample format conversion: %s.\n", error); return -1; } assert(ret == priv->avframe->nb_samples); priv->output = priv->resample_buf; priv->output_left = priv->unitsize * ret; } else #endif { uint64_t unitsize = av_get_bytes_per_sample(avctx->sample_fmt) * (uint64_t)avctx->channels; if (unitsize > 100000) abort(); priv->unitsize = unitsize; uint64_t output_left = unitsize * priv->avframe->nb_samples; if (output_left > 500000000) abort(); priv->output_left = output_left; priv->output = priv->avframe->data[0]; } mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", insize, priv->output_left); return format_result; }
static int decode_new_packet(struct sh_audio *sh) { struct priv *priv = sh->context; AVCodecContext *avctx = priv->avctx; double pts = MP_NOPTS_VALUE; int insize; bool packet_already_used = priv->previous_data_left; struct demux_packet *mpkt = ds_get_packet2(sh->ds, priv->previous_data_left); unsigned char *start; if (!mpkt) { assert(!priv->previous_data_left); start = NULL; insize = 0; ds_parse(sh->ds, &start, &insize, pts, 0); if (insize <= 0) return -1; // error or EOF } else { assert(mpkt->len >= priv->previous_data_left); if (!priv->previous_data_left) { priv->previous_data_left = mpkt->len; pts = mpkt->pts; } insize = priv->previous_data_left; start = mpkt->buffer + mpkt->len - priv->previous_data_left; int consumed = ds_parse(sh->ds, &start, &insize, pts, 0); priv->previous_data_left -= consumed; } AVPacket pkt; av_init_packet(&pkt); pkt.data = start; pkt.size = insize; if (mpkt && mpkt->avpacket) { pkt.side_data = mpkt->avpacket->side_data; pkt.side_data_elems = mpkt->avpacket->side_data_elems; } if (pts != MP_NOPTS_VALUE && !packet_already_used) { sh->pts = pts; sh->pts_bytes = 0; } int got_frame = 0; int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt); // LATM may need many packets to find mux info if (ret == AVERROR(EAGAIN)) return 0; if (ret < 0) { mp_msg(MSGT_DECAUDIO, MSGL_V, "lavc_audio: error\n"); return -1; } if (!sh->parser) priv->previous_data_left += insize - ret; if (!got_frame) return 0; /* An error is reported later from output format checking, but make * sure we don't crash by overreading first plane. */ if (av_sample_fmt_is_planar(avctx->sample_fmt) && avctx->channels > 1) return 0; uint64_t unitsize = (uint64_t)av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels; if (unitsize > 100000) abort(); priv->unitsize = unitsize; uint64_t output_left = unitsize * priv->avframe->nb_samples; if (output_left > 500000000) abort(); priv->output_left = output_left; priv->output = priv->avframe->data[0]; mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", insize, priv->output_left); return 0; }