Example #1
0
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;
}
Example #2
0
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;
}