static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen) { unsigned char *start=NULL; int y,len=-1; while(len<minlen){ AVPacket pkt; int len2=maxlen; double pts; int x=ds_get_packet_pts(sh_audio->ds,&start, &pts); if(x<=0) { start = NULL; x = 0; ds_parse(sh_audio->ds, &start, &x, MP_NOPTS_VALUE, 0); if (x <= 0) break; // error } else { int in_size = x; int consumed = ds_parse(sh_audio->ds, &start, &x, pts, 0); sh_audio->ds->buffer_pos -= in_size - consumed; } av_init_packet(&pkt); pkt.data = start; pkt.size = x; if (pts != MP_NOPTS_VALUE) { sh_audio->pts = pts; sh_audio->pts_bytes = 0; } y=avcodec_decode_audio3(sh_audio->context,(int16_t*)buf,&len2,&pkt); //printf("return:%d samples_out:%d bitstream_in:%d sample_sum:%d\n", y, len2, x, len); fflush(stdout); // LATM may need many packets to find mux info if (y == AVERROR(EAGAIN)) continue; if(y<0){ mp_msg(MSGT_DECAUDIO,MSGL_V,"lavc_audio: error\n");break; } if(!sh_audio->parser && y<x) sh_audio->ds->buffer_pos+=y-x; // put back data (HACK!) if(len2>0){ if (((AVCodecContext *)sh_audio->context)->channels >= 5) { int samplesize = av_get_bytes_per_sample(((AVCodecContext *) sh_audio->context)->sample_fmt); reorder_channel_nch(buf, AF_CHANNEL_LAYOUT_LAVC_DEFAULT, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT, ((AVCodecContext *)sh_audio->context)->channels, len2 / samplesize, samplesize); } //len=len2;break; if(len<0) len=len2; else len+=len2; buf+=len2; maxlen -= len2; sh_audio->pts_bytes += len2; } mp_dbg(MSGT_DECAUDIO,MSGL_DBG2,"Decoded %d -> %d \n",y,len2); if (setup_format(sh_audio, sh_audio->context)) break; } return len; }
static int decode_audio(sh_audio_t *sh, unsigned char *buf, int minlen, int maxlen) { struct spdifContext *spdif_ctx = sh->context; AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx; AVPacket pkt; double pts; int ret, in_size, consumed, x; unsigned char *start = NULL; consumed = spdif_ctx->out_buffer_len = 0; spdif_ctx->out_buffer_size = maxlen; spdif_ctx->out_buffer = buf; while (spdif_ctx->out_buffer_len + spdif_ctx->iec61937_packet_size < maxlen && spdif_ctx->out_buffer_len < minlen) { if (sh->ds->eof) break; x = ds_get_packet_pts(sh->ds, &start, &pts); if (x <= 0) { x = 0; ds_parse(sh->ds, &start, &x, MP_NOPTS_VALUE, 0); if (x == 0) continue; // END_NOT_FOUND in_size = x; } else { in_size = x; consumed = ds_parse(sh->ds, &start, &x, pts, 0); if (x == 0) { mp_msg(MSGT_DECAUDIO,MSGL_V, "start[%p] in_size[%d] consumed[%d] x[%d].\n", start, in_size, consumed, x); continue; // END_NOT_FOUND } sh->ds->buffer_pos -= in_size - consumed; } av_init_packet(&pkt); pkt.data = start; pkt.size = x; mp_msg(MSGT_DECAUDIO,MSGL_V, "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n", start, pkt.size, in_size, consumed, x); if (pts != MP_NOPTS_VALUE) { sh->pts = pts; sh->pts_bytes = 0; } ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt); if (ret < 0) break; } sh->pts_bytes += spdif_ctx->out_buffer_len; return spdif_ctx->out_buffer_len; }
static int init(sh_audio_t *sh, const char *decoder) { int x, in_size, srate, bps, *dtshd_rate; unsigned char *start; double pts; AVFormatContext *lavf_ctx = NULL; AVStream *stream = NULL; const AVOption *opt = NULL; struct spdifContext *spdif_ctx = NULL; spdif_ctx = av_mallocz(sizeof(*spdif_ctx)); if (!spdif_ctx) goto fail; spdif_ctx->lavf_ctx = avformat_alloc_context(); if (!spdif_ctx->lavf_ctx) goto fail; sh->context = spdif_ctx; lavf_ctx = spdif_ctx->lavf_ctx; lavf_ctx->oformat = av_guess_format(FILENAME_SPDIFENC, NULL, NULL); if (!lavf_ctx->oformat) goto fail; lavf_ctx->priv_data = av_mallocz(lavf_ctx->oformat->priv_data_size); if (!lavf_ctx->priv_data) goto fail; lavf_ctx->pb = avio_alloc_context(spdif_ctx->pb_buffer, OUTBUF_SIZE, 1, spdif_ctx, read_packet, write_packet, seek); if (!lavf_ctx->pb) goto fail; stream = avformat_new_stream(lavf_ctx, 0); if (!stream) goto fail; lavf_ctx->duration = AV_NOPTS_VALUE; lavf_ctx->start_time = AV_NOPTS_VALUE; lavf_ctx->streams[0]->codec->codec_id = mp_codec_to_av_codec_id(decoder); lavf_ctx->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; if (AVERROR_PATCHWELCOME == lavf_ctx->oformat->write_header(lavf_ctx)) { mp_msg(MSGT_DECAUDIO,MSGL_INFO, "This codec is not supported by spdifenc.\n"); goto fail; } // get sample_rate & bitrate from parser x = ds_get_packet_pts(sh->ds, &start, &pts); in_size = x; if (x <= 0) { pts = MP_NOPTS_VALUE; x = 0; } ds_parse(sh->ds, &start, &x, pts, 0); srate = 48000; //fake value bps = 768000/8; //fake value if (x && sh->avctx) { // we have parser and large enough buffer if (sh->avctx->sample_rate < 44100) { mp_msg(MSGT_DECAUDIO,MSGL_INFO, "This stream sample_rate[%d Hz] may be broken. " "Force reset 48000Hz.\n", sh->avctx->sample_rate); srate = 48000; //fake value } else srate = sh->avctx->sample_rate; bps = sh->avctx->bit_rate/8; } sh->ds->buffer_pos -= in_size; switch (lavf_ctx->streams[0]->codec->codec_id) { case AV_CODEC_ID_AAC: spdif_ctx->iec61937_packet_size = 16384; sh->sample_format = AF_FORMAT_IEC61937_LE; sh->samplerate = srate; sh->channels = 2; sh->i_bps = bps; break; case AV_CODEC_ID_AC3: spdif_ctx->iec61937_packet_size = 6144; sh->sample_format = AF_FORMAT_AC3_LE; sh->samplerate = srate; sh->channels = 2; sh->i_bps = bps; break; case AV_CODEC_ID_DTS: if(sh->opts->dtshd) { opt = av_opt_find(&lavf_ctx->oformat->priv_class, "dtshd_rate", NULL, 0, 0); if (!opt) goto fail; dtshd_rate = (int*)(((uint8_t*)lavf_ctx->priv_data) + opt->offset); *dtshd_rate = 192000*4; spdif_ctx->iec61937_packet_size = 32768; sh->sample_format = AF_FORMAT_IEC61937_LE; sh->samplerate = 192000; // DTS core require 48000 sh->channels = 2*4; sh->i_bps = bps; } else { spdif_ctx->iec61937_packet_size = 32768; sh->sample_format = AF_FORMAT_AC3_LE; sh->samplerate = srate; sh->channels = 2; sh->i_bps = bps; } break; case AV_CODEC_ID_EAC3: spdif_ctx->iec61937_packet_size = 24576; sh->sample_format = AF_FORMAT_IEC61937_LE; sh->samplerate = 192000; sh->channels = 2; sh->i_bps = bps; break; case AV_CODEC_ID_MP3: spdif_ctx->iec61937_packet_size = 4608; sh->sample_format = AF_FORMAT_MPEG2; sh->samplerate = srate; sh->channels = 2; sh->i_bps = bps; break; case AV_CODEC_ID_TRUEHD: spdif_ctx->iec61937_packet_size = 61440; sh->sample_format = AF_FORMAT_IEC61937_LE; sh->samplerate = 192000; sh->channels = 8; sh->i_bps = bps; break; default: break; } return 1; fail: uninit(sh); return 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; }
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; }