static av_cold void opus_decode_flush(AVCodecContext *ctx) { OpusContext *c = ctx->priv_data; int i; for (i = 0; i < c->nb_streams; i++) { OpusStreamContext *s = &c->streams[i]; memset(&s->packet, 0, sizeof(s->packet)); s->delayed_samples = 0; if (s->celt_delay) av_audio_fifo_drain(s->celt_delay, av_audio_fifo_size(s->celt_delay)); #if CONFIG_SWRESAMPLE swr_close(s->swr); #elif CONFIG_AVRESAMPLE avresample_close(s->avr); #endif av_audio_fifo_drain(c->sync_buffers[i], av_audio_fifo_size(c->sync_buffers[i])); ff_silk_flush(s->silk); ff_celt_flush(s->celt); } }
/** * Requests a frame, if needed, from each input link other than the first. */ static int request_samples(AVFilterContext *ctx, int min_samples) { MixContext *s = ctx->priv; int i, ret; av_assert0(s->nb_inputs > 1); for (i = 1; i < s->nb_inputs; i++) { ret = 0; if (!(s->input_state[i] & INPUT_ON)) continue; if (av_audio_fifo_size(s->fifos[i]) >= min_samples) continue; ret = ff_request_frame(ctx->inputs[i]); if (ret == AVERROR_EOF) { s->input_state[i] |= INPUT_EOF; if (av_audio_fifo_size(s->fifos[i]) == 0) { s->input_state[i] = 0; continue; } } else if (ret < 0) return ret; } return output_frame(ctx->outputs[0]); }
void CAudioEncoder::Encode(AVFrame* inputSample) { AVCodecContext *pContext = m_audioStream->codec; int error; if ((error = av_audio_fifo_realloc(m_fifo, av_audio_fifo_size(m_fifo) + m_frame_size)) < 0) { fprintf(stderr, "Could not reallocate FIFO\n"); return ; } /** Store the new samples in the FIFO buffer. */ if (av_audio_fifo_write(m_fifo, (void **)inputSample->data, inputSample->nb_samples) < m_frame_size) { fprintf(stderr, "Could not write data to FIFO\n"); return ; } do { int current_frame_size = FFMIN(av_audio_fifo_size(m_fifo), m_frame_size); if (current_frame_size < m_frame_size) break; m_tempFrame->nb_samples = current_frame_size; if (av_audio_fifo_read(m_fifo, (void **)m_tempFrame->data, current_frame_size) < current_frame_size) { fprintf(stderr, "Could not read data from FIFO\n"); return; } AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; int got_output; int out_size = avcodec_encode_audio2(pContext, &pkt, m_tempFrame.get(), &got_output); if (got_output) { pkt.stream_index = m_audioStream->index; pkt.pts = av_rescale_q_rnd(pkt.pts, pContext->time_base, m_audioStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); pkt.dts = av_rescale_q_rnd(pkt.dts, pContext->time_base, m_audioStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); pkt.duration = av_rescale_q(pkt.duration, pContext->time_base, m_audioStream->time_base); pkt.pos = -1; //printf("AAC wrote %d bytes \n", pkt.size); auto pContext = m_pfileWriter->GetContext(); av_interleaved_write_frame(pContext, &pkt); //fwrite(pkt.data, 1, pkt.size, m_fileName.get()); } av_free_packet(&pkt); } while (1); }
int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx, AVFrame *frame, int nb_samples) { BufferSinkContext *s = ctx->priv; AVFilterLink *link = ctx->inputs[0]; AVFrame *cur_frame; int ret = 0; #ifdef IDE_COMPILE AVRational tmp; #endif if (!s->audio_fifo) { int nb_channels = link->channels; if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples))) return AVERROR(ENOMEM); } while (ret >= 0) { if (av_audio_fifo_size(s->audio_fifo) >= nb_samples) return read_from_fifo(ctx, frame, nb_samples); if (!(cur_frame = av_frame_alloc())) return AVERROR(ENOMEM); ret = av_buffersink_get_frame_flags(ctx, cur_frame, 0); if (ret == AVERROR_EOF && av_audio_fifo_size(s->audio_fifo)) { av_frame_free(&cur_frame); return read_from_fifo(ctx, frame, av_audio_fifo_size(s->audio_fifo)); } else if (ret < 0) { av_frame_free(&cur_frame); return ret; } if (cur_frame->pts != AV_NOPTS_VALUE) { #ifdef IDE_COMPILE tmp.num = 1; tmp.den = link->sample_rate; s->next_pts = cur_frame->pts - av_rescale_q(av_audio_fifo_size(s->audio_fifo), tmp, link->time_base); #else s->next_pts = cur_frame->pts - av_rescale_q(av_audio_fifo_size(s->audio_fifo), (AVRational){ 1, link->sample_rate }, link->time_base); #endif } ret = av_audio_fifo_write(s->audio_fifo, (void**)cur_frame->extended_data, cur_frame->nb_samples); av_frame_free(&cur_frame); } return ret; }
static int filter_frame(AVFilterLink *link, AVFrame *frame) { AVFilterContext *ctx = link->dst; SidechainCompressContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out = NULL, *in[2] = { NULL }; double *dst; int nb_samples; int i; for (i = 0; i < 2; i++) if (link == ctx->inputs[i]) break; av_assert0(i < 2); av_audio_fifo_write(s->fifo[i], (void **)frame->extended_data, frame->nb_samples); av_frame_free(&frame); nb_samples = FFMIN(av_audio_fifo_size(s->fifo[0]), av_audio_fifo_size(s->fifo[1])); if (!nb_samples) return 0; out = ff_get_audio_buffer(outlink, nb_samples); if (!out) return AVERROR(ENOMEM); for (i = 0; i < 2; i++) { in[i] = ff_get_audio_buffer(ctx->inputs[i], nb_samples); if (!in[i]) { av_frame_free(&in[0]); av_frame_free(&in[1]); av_frame_free(&out); return AVERROR(ENOMEM); } av_audio_fifo_read(s->fifo[i], (void **)in[i]->data, nb_samples); } dst = (double *)out->data[0]; out->pts = s->pts; s->pts += nb_samples; compressor(s, (double *)in[0]->data[0], dst, (double *)in[1]->data[0], nb_samples, s->level_in, s->level_sc, ctx->inputs[0], ctx->inputs[1]); av_frame_free(&in[0]); av_frame_free(&in[1]); return ff_filter_frame(outlink, out); }
static int arequest_frame(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; LoopContext *s = ctx->priv; int ret = 0; if ((!s->size) || (s->nb_samples < s->size) || (s->nb_samples >= s->size && s->loop == 0)) { int nb_samples = av_audio_fifo_size(s->left); if (s->loop == 0 && nb_samples > 0) { AVFrame *out; out = ff_get_audio_buffer(outlink, nb_samples); if (!out) return AVERROR(ENOMEM); av_audio_fifo_read(s->left, (void **)out->extended_data, nb_samples); out->pts = s->pts; s->pts += nb_samples; ret = ff_filter_frame(outlink, out); if (ret < 0) return ret; } ret = ff_request_frame(ctx->inputs[0]); } else { ret = push_samples(ctx, 1024); } if (ret == AVERROR_EOF && s->nb_samples > 0 && s->loop != 0) { ret = push_samples(ctx, outlink->sample_rate); } return ret; }
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples) { int i, ret, size; /* automatically reallocate buffers if needed */ if (av_audio_fifo_space(af) < nb_samples) { int current_size = av_audio_fifo_size(af); /* check for integer overflow in new size calculation */ if (INT_MAX / 2 - current_size < nb_samples) return AVERROR(EINVAL); /* reallocate buffers */ if ((ret = av_audio_fifo_realloc(af, 2 * (current_size + nb_samples))) < 0) return ret; } size = nb_samples * af->sample_size; for (i = 0; i < af->nb_buffers; i++) { ret = av_fifo_generic_write(af->buf[i], data[i], size, NULL); if (ret != size) return AVERROR_BUG; } af->nb_samples += nb_samples; return nb_samples; }
/** * Load one audio frame from the FIFO buffer, encode and write it to the * output file. * @param fifo Buffer used for temporary storage * @param output_format_context Format context of the output file * @param output_codec_context Codec context of the output file * @return Error code (0 if successful) */ int Transcode::load_encode_and_write(AVAudioFifo *fifo, AVFormatContext *output_format_context, AVCodecContext *output_codec_context) { /* Temporary storage of the output samples of the frame written to the file. */ AVFrame *output_frame; /* Use the maximum number of possible samples per frame. * If there is less than the maximum possible frame size in the FIFO * buffer use this number. Otherwise, use the maximum possible frame size. */ const int frame_size = FFMIN(av_audio_fifo_size(fifo), output_codec_context->frame_size); int data_written; /* Initialize temporary storage for one output frame. */ if (init_output_frame(&output_frame, output_codec_context, frame_size)) return AVERROR_EXIT; /* Read as many samples from the FIFO buffer as required to fill the frame. * The samples are stored in the frame temporarily. */ if (av_audio_fifo_read(fifo, (void **)output_frame->data, frame_size) < frame_size) { fprintf(stderr, "Could not read data from FIFO\n"); av_frame_free(&output_frame); return AVERROR_EXIT; } /* Encode one frame worth of audio samples. */ if (encode_audio_frame(output_frame, output_format_context, output_codec_context, &data_written)) { av_frame_free(&output_frame); return AVERROR_EXIT; } av_frame_free(&output_frame); return 0; }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; ShowFreqsContext *s = ctx->priv; AVFrame *fin = NULL; int ret = 0; av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples); while (av_audio_fifo_size(s->fifo) >= s->win_size) { fin = ff_get_audio_buffer(inlink, s->win_size); if (!fin) { ret = AVERROR(ENOMEM); goto fail; } fin->pts = s->pts; s->pts += s->skip_samples; ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size); if (ret < 0) goto fail; ret = plot_freqs(inlink, fin); av_frame_free(&fin); av_audio_fifo_drain(s->fifo, s->skip_samples); if (ret < 0) goto fail; } fail: av_frame_free(&fin); av_frame_free(&in); return ret; }
/** * Load one audio frame from the FIFO buffer, encode and write it to the * output file. */ int AudioDecoder::load_encode(AVPacket& output_packet) { /** Temporary storage of the output samples of the frame written to the file. */ AVFrame *output_frame; /** * Use the maximum number of possible samples per frame. * If there is less than the maximum possible frame size in the FIFO * buffer use this number. Otherwise, use the maximum possible frame size */ const int frame_size = FFMIN(av_audio_fifo_size(fifo), output_codec_context->frame_size); /** Initialize temporary storage for one output frame. */ if (init_output_frame(&output_frame, output_codec_context, frame_size)) { ELOG_WARN(" init_output_frame failed!! frame_size=%d", frame_size); return 0; } /** * Read as many samples from the FIFO buffer as required to fill the frame. * The samples are stored in the frame temporarily. */ if (av_audio_fifo_read(fifo, (void **)output_frame->data, frame_size) < frame_size) { ELOG_WARN("Could not read data from FIFO\n"); av_frame_free(&output_frame); return 0; } ELOG_DEBUG("fifo read %d, now left %d", frame_size, av_audio_fifo_size(fifo)); /** Encode one frame worth of audio samples. */ int pktlen = encode_audio_frame(output_frame, output_packet); if (pktlen <= 0) { ELOG_WARN("Failed to encode_audio_frame!!"); } av_frame_free(&output_frame); return pktlen; }
int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **pbuf, int nb_samples) { BufferSinkContext *s = ctx->priv; AVFilterLink *link = ctx->inputs[0]; int ret = 0; if (!s->audio_fifo) { int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples))) return AVERROR(ENOMEM); } while (ret >= 0) { AVFilterBufferRef *buf; if (av_audio_fifo_size(s->audio_fifo) >= nb_samples) return read_from_fifo(ctx, pbuf, nb_samples); ret = av_buffersink_read(ctx, &buf); if (ret == AVERROR_EOF && av_audio_fifo_size(s->audio_fifo)) return read_from_fifo(ctx, pbuf, av_audio_fifo_size(s->audio_fifo)); else if (ret < 0) return ret; if (buf->pts != AV_NOPTS_VALUE) { s->next_pts = buf->pts - av_rescale_q(av_audio_fifo_size(s->audio_fifo), (AVRational){ 1, link->sample_rate }, link->time_base); } ret = av_audio_fifo_write(s->audio_fifo, (void**)buf->extended_data, buf->audio->nb_samples); avfilter_unref_buffer(buf); } return ret; }
/** * Requests a frame, if needed, from each input link other than the first. */ static int request_samples(AVFilterContext *ctx, int min_samples) { MixContext *s = ctx->priv; int i, ret; av_assert0(s->nb_inputs > 1); for (i = 1; i < s->nb_inputs; i++) { ret = 0; if (s->input_state[i] == INPUT_OFF) continue; while (!ret && av_audio_fifo_size(s->fifos[i]) < min_samples) ret = ff_request_frame(ctx->inputs[i]); if (ret == AVERROR_EOF) { if (av_audio_fifo_size(s->fifos[i]) == 0) { s->input_state[i] = INPUT_OFF; continue; } } else if (ret < 0) return ret; } return 0; }
int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx, AVFrame *frame, int nb_samples) { BufferSinkContext *s = ctx->priv; AVFilterLink *link = ctx->inputs[0]; int ret = 0; if (!s->audio_fifo) { int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples))) return AVERROR(ENOMEM); } while (ret >= 0) { if (av_audio_fifo_size(s->audio_fifo) >= nb_samples) return read_from_fifo(ctx, frame, nb_samples); ret = ff_request_frame(link); if (ret == AVERROR_EOF && av_audio_fifo_size(s->audio_fifo)) return read_from_fifo(ctx, frame, av_audio_fifo_size(s->audio_fifo)); else if (ret < 0) return ret; if (s->cur_frame->pts != AV_NOPTS_VALUE) { s->next_pts = s->cur_frame->pts - av_rescale_q(av_audio_fifo_size(s->audio_fifo), (AVRational){ 1, link->sample_rate }, link->time_base); } ret = av_audio_fifo_write(s->audio_fifo, (void**)s->cur_frame->extended_data, s->cur_frame->nb_samples); av_frame_free(&s->cur_frame); } return ret; }
int AudioDecoder::add_samples_to_fifo(AVAudioFifo *fifo, uint8_t **converted_input_samples, const int frame_size) { int error; /** * Make the FIFO as large as it needs to be to hold both, * the old and the new samples. */ if ((error = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) { ELOG_WARN("Could not reallocate FIFO"); return error; } /** Store the new samples in the FIFO buffer. */ if (av_audio_fifo_write(fifo, (void **)converted_input_samples, frame_size) < frame_size) { ELOG_WARN("Could not write data to FIFO"); return AVERROR_EXIT; } ELOG_DEBUG("added frame to fifo, now size %d", av_audio_fifo_size(fifo)); return 0; }
static int request_frame(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; SidechainCompressContext *s = ctx->priv; int i; /* get a frame on each input */ for (i = 0; i < 2; i++) { AVFilterLink *inlink = ctx->inputs[i]; if (!av_audio_fifo_size(s->fifo[i])) return ff_request_frame(inlink); } return 0; }
static int opus_flush_resample(OpusStreamContext *s, int nb_samples) { int celt_size = av_audio_fifo_size(s->celt_delay); int ret, i; #if CONFIG_SWRESAMPLE ret = swr_convert(s->swr, (uint8_t**)s->out, nb_samples, NULL, 0); #elif CONFIG_AVRESAMPLE ret = avresample_convert(s->avr, (uint8_t**)s->out, s->out_size, nb_samples, NULL, 0, 0); #endif if (ret < 0) return ret; else if (ret != nb_samples) { av_log(s->avctx, AV_LOG_ERROR, "Wrong number of flushed samples: %d\n", ret); return AVERROR_BUG; } if (celt_size) { if (celt_size != nb_samples) { av_log(s->avctx, AV_LOG_ERROR, "Wrong number of CELT delay samples.\n"); return AVERROR_BUG; } av_audio_fifo_read(s->celt_delay, (void**)s->celt_output, nb_samples); for (i = 0; i < s->output_channels; i++) { s->fdsp->vector_fmac_scalar(s->out[i], s->celt_output[i], 1.0, nb_samples); } } if (s->redundancy_idx) { for (i = 0; i < s->output_channels; i++) opus_fade(s->out[i], s->out[i], s->redundancy_output[i] + 120 + s->redundancy_idx, ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx); s->redundancy_idx = 0; } s->out[0] += nb_samples; s->out[1] += nb_samples; s->out_size -= nb_samples * sizeof(float); return 0; }
/** * Requests a frame, if needed, from each input link other than the first. */ static int request_samples(AVFilterContext *ctx, int min_samples) { MixContext *s = ctx->priv; int i; av_assert0(s->nb_inputs > 1); for (i = 1; i < s->nb_inputs; i++) { if (!(s->input_state[i] & INPUT_ON) || (s->input_state[i] & INPUT_EOF)) continue; if (av_audio_fifo_size(s->fifos[i]) >= min_samples) continue; ff_inlink_request_frame(ctx->inputs[i]); } return output_frame(ctx->outputs[0]); }
/** * Returns the smallest number of samples available in the input FIFOs other * than that of the first input. */ static int get_available_samples(MixContext *s) { int i; int available_samples = INT_MAX; av_assert0(s->nb_inputs > 1); for (i = 1; i < s->nb_inputs; i++) { int nb_samples; if (s->input_state[i] == INPUT_OFF) continue; nb_samples = av_audio_fifo_size(s->fifos[i]); available_samples = FFMIN(available_samples, nb_samples); } if (available_samples == INT_MAX) return 0; return available_samples; }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AudioSurroundContext *s = ctx->priv; av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples); if (s->pts == AV_NOPTS_VALUE) s->pts = in->pts; av_frame_free(&in); while (av_audio_fifo_size(s->fifo) >= s->buf_size) { AVFrame *out; int ret; ret = av_audio_fifo_peek(s->fifo, (void **)s->input->extended_data, s->buf_size); if (ret < 0) return ret; ctx->internal->execute(ctx, fft_channel, NULL, NULL, inlink->channels); s->filter(ctx); out = ff_get_audio_buffer(outlink, s->hop_size); if (!out) return AVERROR(ENOMEM); ctx->internal->execute(ctx, ifft_channel, out, NULL, outlink->channels); out->pts = s->pts; if (s->pts != AV_NOPTS_VALUE) s->pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); av_audio_fifo_drain(s->fifo, s->hop_size); ret = ff_filter_frame(outlink, out); if (ret < 0) return ret; } return 0; }
static av_cold void opus_decode_flush(AVCodecContext *ctx) { OpusContext *c = ctx->priv_data; int i; for (i = 0; i < c->nb_streams; i++) { OpusStreamContext *s = &c->streams[i]; memset(&s->packet, 0, sizeof(s->packet)); s->delayed_samples = 0; if (s->celt_delay) av_audio_fifo_drain(s->celt_delay, av_audio_fifo_size(s->celt_delay)); swr_close(s->swr); ff_silk_flush(s->silk); ff_celt_flush(s->celt); } }
static int handle_buffered_output(AVAudioResampleContext *avr, AudioData *output, AudioData *converted) { int ret; if (!output || av_audio_fifo_size(avr->out_fifo) > 0 || (converted && output->allocated_samples < converted->nb_samples)) { if (converted) { /* if there are any samples in the output FIFO or if the user-supplied output buffer is not large enough for all samples, we add to the output FIFO */ av_dlog(avr, "[FIFO] add %s to out_fifo\n", converted->name); ret = ff_audio_data_add_to_fifo(avr->out_fifo, converted, 0, converted->nb_samples); if (ret < 0) return ret; } /* if the user specified an output buffer, read samples from the output FIFO to the user output */ if (output && output->allocated_samples > 0) { av_dlog(avr, "[FIFO] read from out_fifo to output\n"); av_dlog(avr, "[end conversion]\n"); return ff_audio_data_read_from_fifo(avr->out_fifo, output, output->allocated_samples); } } else if (converted) { /* copy directly to output if it is large enough or there is not any data in the output FIFO */ av_dlog(avr, "[copy] %s to output\n", converted->name); output->nb_samples = 0; ret = ff_audio_data_copy(output, converted, avr->remap_point == REMAP_OUT_COPY ? &avr->ch_map_info : NULL); if (ret < 0) return ret; av_dlog(avr, "[end conversion]\n"); return output->nb_samples; } av_dlog(avr, "[end conversion]\n"); return 0; }
int AudioEncode::doEncode(AVPacket * pkt, const uint8_t ** data, int nb_samples) { assert(pkt); assert(data); int ret = av_audio_fifo_write(mFifo, (void **)data, nb_samples); if (ret < 0) { fprintf(stderr, "write audio data into FIFO failed: %s\n", av_err2str(ret)); exit(1); } int got_pkt = 0; while (av_audio_fifo_size(mFifo) > mMaxSamplesCount) { av_init_packet(pkt); int nb_samples = av_audio_fifo_read(mFifo, (void **)mData, mMaxSamplesCount); if (nb_samples < 0) { fprintf(stderr, "read audio data from FIFO failed: %s\n", av_err2str(nb_samples)); exit(1); } if (!mFrame) { mFrame = avcodec_alloc_frame(); mFrame->pts = 0; } mFrame->pts++; int bytes = av_samples_get_buffer_size(NULL,mChannelNum,nb_samples,mSampleFmt,0); avcodec_fill_audio_frame(mFrame,mChannelNum,mSampleFmt,mData[0],bytes,0); int ret = avcodec_encode_audio2(mCodecCtx, pkt, mFrame, &got_pkt); if (ret < 0) { fprintf(stderr, "encode audio data failed: %s\n", av_err2str(ret)); exit(1); } if (!got_pkt) { avcodec_encode_audio2(mCodecCtx, pkt, NULL, &got_pkt); continue; } } return 0; }
/** * Add converted input audio samples to the FIFO buffer for later processing. * @param fifo Buffer to add the samples to * @param converted_input_samples Samples to be added. The dimensions are channel * (for multi-channel audio), sample. * @param frame_size Number of samples to be converted * @return Error code (0 if successful) */ int Transcode::add_samples_to_fifo(AVAudioFifo *fifo, uint8_t **converted_input_samples, const int frame_size) { int error; /* Make the FIFO as large as it needs to be to hold both, * the old and the new samples. */ if ((error = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) { fprintf(stderr, "Could not reallocate FIFO\n"); return error; } /* Store the new samples in the FIFO buffer. */ if (av_audio_fifo_write(fifo, (void **)converted_input_samples, frame_size) < frame_size) { fprintf(stderr, "Could not write data to FIFO\n"); return AVERROR_EXIT; } return 0; }
static int encode_next(stream_t *stream) { int result, got_packet; AVFrame *frame = stream->encode_frame; AVPacket *packet = &stream->encode_packet; while (av_audio_fifo_size(stream->src_buf) < stream->encoder->frame_size) { result = decode_next(stream); if (result <= 0) { return result; } } av_audio_fifo_read(stream->src_buf, (void **)frame->extended_data, stream->encoder->frame_size); av_free_packet(packet); result = avcodec_encode_audio2(stream->encoder, packet, frame, &got_packet); if (result < 0) { musicd_log(LOG_ERROR, "stream", "can't encode: %s", strerror(AVUNERROR(result))); return -1; } if (!got_packet) { return 1; } stream->dst_data = packet->data; stream->dst_size = packet->size; return 1; }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AFFTFiltContext *s = ctx->priv; const int window_size = s->window_size; const float f = 1. / s->win_scale; double values[VAR_VARS_NB]; AVFrame *out, *in = NULL; int ch, n, ret, i, j, k; int start = s->start, end = s->end; av_audio_fifo_write(s->fifo, (void **)frame->extended_data, frame->nb_samples); av_frame_free(&frame); while (av_audio_fifo_size(s->fifo) >= window_size) { if (!in) { in = ff_get_audio_buffer(outlink, window_size); if (!in) return AVERROR(ENOMEM); } ret = av_audio_fifo_peek(s->fifo, (void **)in->extended_data, window_size); if (ret < 0) break; for (ch = 0; ch < inlink->channels; ch++) { const float *src = (float *)in->extended_data[ch]; FFTComplex *fft_data = s->fft_data[ch]; for (n = 0; n < in->nb_samples; n++) { fft_data[n].re = src[n] * s->window_func_lut[n]; fft_data[n].im = 0; } for (; n < window_size; n++) { fft_data[n].re = 0; fft_data[n].im = 0; } } values[VAR_PTS] = s->pts; values[VAR_SAMPLE_RATE] = inlink->sample_rate; values[VAR_NBBINS] = window_size / 2; values[VAR_CHANNELS] = inlink->channels; for (ch = 0; ch < inlink->channels; ch++) { FFTComplex *fft_data = s->fft_data[ch]; float *buf = (float *)s->buffer->extended_data[ch]; int x; values[VAR_CHANNEL] = ch; av_fft_permute(s->fft, fft_data); av_fft_calc(s->fft, fft_data); for (n = 0; n < window_size / 2; n++) { float fr, fi; values[VAR_BIN] = n; fr = av_expr_eval(s->real[ch], values, s); fi = av_expr_eval(s->imag[ch], values, s); fft_data[n].re *= fr; fft_data[n].im *= fi; } for (n = window_size / 2 + 1, x = window_size / 2 - 1; n < window_size; n++, x--) { fft_data[n].re = fft_data[x].re; fft_data[n].im = -fft_data[x].im; } av_fft_permute(s->ifft, fft_data); av_fft_calc(s->ifft, fft_data); start = s->start; end = s->end; k = end; for (i = 0, j = start; j < k && i < window_size; i++, j++) { buf[j] += s->fft_data[ch][i].re * f; } for (; i < window_size; i++, j++) { buf[j] = s->fft_data[ch][i].re * f; } start += s->hop_size; end = j; } s->start = start; s->end = end; if (start >= window_size) { float *dst, *buf; start -= window_size; end -= window_size; s->start = start; s->end = end; out = ff_get_audio_buffer(outlink, window_size); if (!out) { ret = AVERROR(ENOMEM); break; } out->pts = s->pts; s->pts += window_size; for (ch = 0; ch < inlink->channels; ch++) { dst = (float *)out->extended_data[ch]; buf = (float *)s->buffer->extended_data[ch]; for (n = 0; n < window_size; n++) { dst[n] = buf[n] * (1 - s->overlap); } memmove(buf, buf + window_size, window_size * 4); } ret = ff_filter_frame(outlink, out); if (ret < 0) break; } av_audio_fifo_drain(s->fifo, s->hop_size); } av_frame_free(&in); return ret; }
int udpsocket::ts_demux(void) { AVCodec *pVideoCodec[VIDEO_NUM]; AVCodec *pAudioCodec[AUDIO_NUM]; AVCodecContext *pVideoCodecCtx[VIDEO_NUM]; AVCodecContext *pAudioCodecCtx[AUDIO_NUM]; AVIOContext * pb; AVInputFormat *piFmt; AVFormatContext *pFmt; uint8_t *buffer; int videoindex[VIDEO_NUM]; int audioindex[AUDIO_NUM]; AVStream *pVst[VIDEO_NUM]; AVStream *pAst[AUDIO_NUM]; AVFrame *pVideoframe[VIDEO_NUM]; AVFrame *pAudioframe[AUDIO_NUM]; AVFrame *pOutAudioframe[AUDIO_NUM]; AVFrame *pOutAudioframelast[AUDIO_NUM]; AVPacket pkt; int got_picture; int video_num[VIDEO_NUM]; int audio_num[AUDIO_NUM]; int frame_size; //transcodepool transcodepool* pVideoTransPool[VIDEO_NUM]; transcodepool* pAudioTransPool[AUDIO_NUM]; for( int i=0; i<VIDEO_NUM; i++ ){ pVideoCodec[i] = NULL; pVideoCodecCtx[i] =NULL; videoindex[i] = -1; pVst[i] = NULL; video_num[i] = 0; pVideoframe[i] = NULL; pVideoframe[i] = av_frame_alloc(); pVideoTransPool[i] = NULL; } for( int i=0; i<AUDIO_NUM; i++ ){ pAudioCodec[i] = NULL; pAudioCodecCtx[i] = NULL; audioindex[i] = -1; pAst[i] = NULL; audio_num[i] = 0; pOutAudioframe[i] = NULL; pOutAudioframe[i] = av_frame_alloc(); pOutAudioframelast[i] = NULL; pOutAudioframelast[i] = av_frame_alloc(); pAudioframe[i] = NULL; pAudioframe[i] = av_frame_alloc(); pAudioTransPool[i] = NULL; } pb = NULL; piFmt = NULL; pFmt = NULL; buffer = (uint8_t*)av_mallocz(sizeof(uint8_t)*BUFFER_SIZE); got_picture = 0; frame_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*3/2; //encoder AVFormatContext *ofmt_ctx = NULL; AVPacket enc_pkt; AVStream *out_stream; AVCodecContext *enc_ctx; AVCodec *encoder; AVFormatContext *outAudioFormatCtx[AUDIO_NUM]; AVPacket audio_pkt; AVStream *audio_stream[AUDIO_NUM]; AVCodecContext *AudioEncodeCtx[AUDIO_NUM]; AVCodec *AudioEncoder[AUDIO_NUM]; fp_v = fopen("OUT.h264","wb+"); //输出文件 fp_a = fopen("audio_out.aac","wb+"); //FFMPEG av_register_all(); pb = avio_alloc_context(buffer, 4096, 0, NULL, read_data, NULL, NULL); // printf("thread %d pid %lu tid %lu\n",index,(unsigned long)getpid(),(unsigned long)pthread_self()); if (!pb) { fprintf(stderr, "avio alloc failed!\n"); return -1; } int x = av_probe_input_buffer(pb, &piFmt, "", NULL, 0, 0); if (x < 0) { printf("probe error: %d",x); // fprintf(stderr, "probe failed!\n"); } else { fprintf(stdout, "probe success!\n"); fprintf(stdout, "format: %s[%s]\n", piFmt->name, piFmt->long_name); } pFmt = avformat_alloc_context(); pFmt->pb = pb; if (avformat_open_input(&pFmt, "", piFmt, NULL) < 0) { fprintf(stderr, "avformat open failed.\n"); return -1; } else { fprintf(stdout, "open stream success!\n"); } //pFmt->probesize = 4096 * 2000; //pFmt->max_analyze_duration = 5 * AV_TIME_BASE; //pFmt->probesize = 2048; // pFmt->max_analyze_duration = 1000; pFmt->probesize = 2048 * 1000 ; pFmt->max_analyze_duration = 2048 * 1000; if (avformat_find_stream_info(pFmt,0) < 0) { fprintf(stderr, "could not fine stream.\n"); return -1; } printf("dump format\n"); av_dump_format(pFmt, 0, "", 0); int videox = 0,audiox = 0; for (int i = 0; i < pFmt->nb_streams; i++) { if(videox == 7 && audiox == 7) break; if ( pFmt->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && videox < 7 ) { videoindex[ videox++ ] = i; } if ( pFmt->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audiox < 7 ) { audioindex[ audiox++ ] = i; } } for(int i=0; i<VIDEO_NUM; i++) printf("videoindex %d = %d, audioindex %d = %d\n",i , videoindex[i], i ,audioindex[i]); if (videoindex[6] < 0 || audioindex[6] < 0) { fprintf(stderr, "videoindex=%d, audioindex=%d\n", videoindex[6], audioindex[6]); return -1; } for( int i=0; i<VIDEO_NUM; i++ ){ pVst[i] = pFmt->streams[videoindex[i]]; pVideoCodecCtx[i] = pVst[i]->codec; pVideoCodec[i] = avcodec_find_decoder(pVideoCodecCtx[i]->codec_id); if (!pVideoCodec[i]) { fprintf(stderr, "could not find video decoder!\n"); return -1; } if (avcodec_open2(pVideoCodecCtx[i], pVideoCodec[i], NULL) < 0) { fprintf(stderr, "could not open video codec!\n"); return -1; } } for( int i=0; i<AUDIO_NUM; i++ ){ pAst[i] = pFmt->streams[audioindex[i]]; pAudioCodecCtx[i] = pAst[i]->codec; pAudioCodec[i] = avcodec_find_decoder(pAudioCodecCtx[i]->codec_id); if (!pAudioCodec[i]) { fprintf(stderr, "could not find audio decoder!\n"); return -1; } if (avcodec_open2(pAudioCodecCtx[i], pAudioCodec[i], NULL) < 0) { fprintf(stderr, "could not open audio codec!\n"); return -1; } } //video encoder init avformat_alloc_output_context2(&ofmt_ctx, NULL, "h264", NULL); unsigned char* outbuffer = NULL; outbuffer = (unsigned char*)av_malloc(1024*1000); AVIOContext *avio_out = NULL; avio_out = avio_alloc_context(outbuffer, 1024*1000, 0, NULL, NULL, write_buffer,NULL); if(avio_out == NULL){ printf("avio_out error\n"); return -1; } ofmt_ctx->pb = avio_out; ofmt_ctx->flags = AVFMT_FLAG_CUSTOM_IO; out_stream = avformat_new_stream(ofmt_ctx, NULL); if(!out_stream){ av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n"); return -1; } enc_ctx = out_stream->codec; encoder = avcodec_find_encoder(AV_CODEC_ID_H264); enc_ctx->height = pVideoCodecCtx[0]->height; enc_ctx->width = pVideoCodecCtx[0]->width; enc_ctx->sample_aspect_ratio = pVideoCodecCtx[0]->sample_aspect_ratio; enc_ctx->pix_fmt = encoder->pix_fmts[0]; out_stream->time_base = pVst[0]->time_base; // out_stream->time_base.num = 1; // out_stream->time_base.den = 25; enc_ctx->me_range = 16; enc_ctx->max_qdiff = 4; enc_ctx->qmin = 25; enc_ctx->qmax = 40; enc_ctx->qcompress = 0.6; enc_ctx->refs = 3; enc_ctx->bit_rate = 1000000; int re = avcodec_open2(enc_ctx, encoder, NULL); if (re < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream \n"); return re; } if(ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; re = avformat_write_header(ofmt_ctx, NULL); if(re < 0){ av_log(NULL, AV_LOG_ERROR, "Error occured when opening output file\n"); return re; } //audio encoder for( int i=0; i<AUDIO_NUM; i++){ outAudioFormatCtx[i] = NULL; // audio_pkt = NULL; audio_stream[i] = NULL; AudioEncodeCtx[i] = NULL; AudioEncoder[i] = NULL; } const char* out_audio_file = "transcodeaudio.aac"; //Output URL //Method 1. outAudioFormatCtx[0] = avformat_alloc_context(); outAudioFormatCtx[0]->oformat = av_guess_format(NULL, out_audio_file, NULL); AVIOContext *avio_audio_out = NULL; avio_audio_out = avio_alloc_context(outbuffer, 1024*1000, 0, NULL, NULL, write_buffer,NULL); if(avio_audio_out == NULL){ printf("avio_out error\n"); return -1; } outAudioFormatCtx[0]->pb = avio_audio_out; //Method 2. //avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file); //fmt = pFormatCtx->oformat; //Open output URL if (avio_open(&outAudioFormatCtx[0]->pb,out_audio_file, AVIO_FLAG_READ_WRITE) < 0){ printf("Failed to open output file!\n"); return -1; } //Show some information av_dump_format(outAudioFormatCtx[0], 0, out_audio_file, 1); AudioEncoder[0] = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!AudioEncoder[0]){ printf("Can not find encoder!\n"); return -1; } audio_stream[0] = avformat_new_stream(outAudioFormatCtx[0], AudioEncoder[0]); if (audio_stream[0]==NULL){ return -1; } AudioEncodeCtx[0] = audio_stream[0]->codec; AudioEncodeCtx[0]->codec_id = outAudioFormatCtx[0]->oformat->audio_codec; AudioEncodeCtx[0]->codec_type = AVMEDIA_TYPE_AUDIO; AudioEncodeCtx[0]->sample_fmt = AV_SAMPLE_FMT_S16; AudioEncodeCtx[0]->sample_rate= 48000;//44100 AudioEncodeCtx[0]->channel_layout=AV_CH_LAYOUT_STEREO; AudioEncodeCtx[0]->channels = av_get_channel_layout_nb_channels(AudioEncodeCtx[0]->channel_layout); AudioEncodeCtx[0]->bit_rate = 64000;//64000 /** Allow the use of the experimental AAC encoder */ AudioEncodeCtx[0]->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; /** Set the sample rate for the container. */ audio_stream[0]->time_base.den = pAudioCodecCtx[0]->sample_rate; audio_stream[0]->time_base.num = 1; if (avcodec_open2(AudioEncodeCtx[0], AudioEncoder[0],NULL) < 0){ printf("Failed to open encoder!\n"); return -1; } av_samples_get_buffer_size(NULL, AudioEncodeCtx[0]->channels,AudioEncodeCtx[0]->frame_size,AudioEncodeCtx[0]->sample_fmt, 1); //uint8_t samples[AVCODEC_MAX_AUDIO_FRAME_SIZE*3/2]; av_init_packet(&pkt); av_init_packet(&audio_pkt); av_init_packet(&enc_pkt); AVAudioFifo *af = NULL; SwrContext *resample_context = NULL; long long pts = 0; /** Initialize the resampler to be able to convert audio sample formats. */ // if (init_resampler(input_codec_context, output_codec_context, // &resample_context)) for(int i=0; i<1; i++){ printf("work \n"); printf(" samplerate input = %d , samplerate output = %d\n",pAudioCodecCtx[i]->sample_rate, AudioEncodeCtx[i]->sample_rate); resample_context = swr_alloc_set_opts(NULL, av_get_default_channel_layout(AudioEncodeCtx[i]->channels), AudioEncodeCtx[i]->sample_fmt, AudioEncodeCtx[i]->sample_rate, av_get_default_channel_layout(pAudioCodecCtx[i]->channels), pAudioCodecCtx[i]->sample_fmt, pAudioCodecCtx[i]->sample_rate, 0, NULL); swr_init(resample_context); } af = av_audio_fifo_alloc(AudioEncodeCtx[0]->sample_fmt, AudioEncodeCtx[0]->channels, 1); if(af == NULL) { printf("error af \n"); return -1; } while(1) { if (av_read_frame(pFmt, &pkt) >= 0) { for( int i=0; i<1; i++ ){ if (pkt.stream_index == videoindex[i]) { // av_frame_free(&pframe); avcodec_decode_video2(pVideoCodecCtx[i], pVideoframe[i], &got_picture, &pkt); if (got_picture) { if(videoindex[i] == 0){ // m_tsRecvPool->write_buffer(pkt.data, pkt.size); pVideoframe[i]->pts = av_frame_get_best_effort_timestamp(pVideoframe[i]); pVideoframe[i]->pict_type = AV_PICTURE_TYPE_NONE; // printf("videoframesize0 = %d, size1 = %d, size2 = %d, size3 = %d, size4 = %d,format = %d\n",pVideoframe[i]->linesize[0], // pVideoframe[i]->linesize[1],pVideoframe[i]->linesize[2],pVideoframe[i]->linesize[3],pVideoframe[i]->linesize[4],pVideoframe[i]->format); // pVideoTransPool[i]->PutFrame( pVideoframe[i] ,i); int enc_got_frame = 0; /* ffmpeg encoder */ enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet(&enc_pkt); re = avcodec_encode_video2(ofmt_ctx->streams[videoindex[i]]->codec, &enc_pkt, pVideoframe[i], &enc_got_frame); // printf("enc_got_frame =%d, re = %d \n",enc_got_frame, re); printf("video Encode 1 Packet\tsize:%d\tpts:%lld\n",enc_pkt.size,enc_pkt.pts); /* prepare packet for muxing */ // fwrite(enc_pkt.data,enc_pkt.size, 1, fp_v); } // printf(" video %d decode %d num\n", i, video_num[i]++); break; } }else if (pkt.stream_index == audioindex[i]) { if (avcodec_decode_audio4(pAudioCodecCtx[i], pAudioframe[i], &frame_size, &pkt) >= 0) { if (i == 0){ // fwrite(pAudioframe[i]->data[0],pAudioframe[i]->linesize[0], 1, fp_a); // printf("index = %d audio %d decode %d num\n", index, i, audio_num[i]++); uint8_t *converted_input_samples = NULL; converted_input_samples = (uint8_t *)calloc(AudioEncodeCtx[i]->channels, sizeof(*converted_input_samples)); av_samples_alloc(&converted_input_samples, NULL, AudioEncodeCtx[i]->channels, pAudioframe[i]->nb_samples, AudioEncodeCtx[i]->sample_fmt, 0); int error = 0; if((error = swr_convert(resample_context, &converted_input_samples, pAudioframe[i]->nb_samples, (const uint8_t**)pAudioframe[i]->extended_data, pAudioframe[i]->nb_samples))<0){ printf("error : %d\n",error); } // av_audio_fifo_realloc(af, av_audio_fifo_size(af) + pAudioframe[i]->nb_samples); av_audio_fifo_write(af, (void **)&converted_input_samples, pAudioframe[i]->nb_samples); // fwrite(pkt.data,pkt.size, 1, fp_a); // pAudioframe[i]->data[0] = frame_buf; // init_converted_samples(&converted_input_samples, output_codec_context, pAudioframe[i]->nb_samples); /** Initialize temporary storage for one output frame. */ // printf("pkt.size = %d , pkt.pts = %d ,pkt.dts = %d\n",pkt.size, pkt.pts, pkt.dts); // printf("framesize = %d, audioframesize = %d\n", pAudioframe[i]->nb_samples, frame_size); // pOutAudioframe[i]->pict_type = AV_PICTURE_TYPE_NONE; int got_frame=0; //Encode // av_init_packet(&audio_pkt); // audio_pkt.data = NULL; // audio_pkt.size = 0; // avcodec_encode_audio2(AudioEncodeCtx[0], &audio_pkt, pOutAudioframe[i], &got_frame); // printf("Encode 1 Packet\tsize:%d\tpts:%lld\n", audio_pkt.size, audio_pkt.pts); while(av_audio_fifo_size(af) >= AudioEncodeCtx[i]->frame_size){ int frame_size = FFMIN(av_audio_fifo_size(af),AudioEncodeCtx[0]->frame_size); pOutAudioframe[i]->nb_samples = frame_size; pOutAudioframe[i]->channel_layout = AudioEncodeCtx[0]->channel_layout; pOutAudioframe[i]->sample_rate = AudioEncodeCtx[0]->sample_rate; pOutAudioframe[i]->format = AudioEncodeCtx[0]->sample_fmt; av_frame_get_buffer(pOutAudioframe[i], 0); av_audio_fifo_read(af, (void **)&pOutAudioframe[i]->data, frame_size); pOutAudioframe[i]->pts=pts; pts += pOutAudioframe[i]->nb_samples; audio_pkt.data = NULL; audio_pkt.size = 0; av_init_packet(&audio_pkt); avcodec_encode_audio2(AudioEncodeCtx[0], &audio_pkt, pOutAudioframe[i], &got_frame); printf("audio Encode 1 Packet\tsize:%d\tpts:%lld\n", audio_pkt.size, audio_pkt.pts); fwrite(audio_pkt.data,audio_pkt.size, 1, fp_a); } } // if(i == 0){ // fwrite(pkt.data,pkt.size, 1, fp_a); // } // printf("index = %d audio %d decode %d num\n", index, i, audio_num[i]++); break; } } } av_free_packet(&pkt); av_free_packet(&enc_pkt); } } av_free(buffer); for(int i=0; i<VIDEO_NUM; i++) av_free(pVideoframe[i]); for(int i=0; i<AUDIO_NUM; i++) av_free(pAudioframe[i]); return 0; }
/** Convert an audio file to an AAC file in an MP4 container. */ int compress(int argc, char **argv) { AVFormatContext *input_format_context = NULL, *output_format_context = NULL; AVCodecContext *input_codec_context = NULL, *output_codec_context = NULL; SwrContext *resample_context = NULL; AVAudioFifo *fifo = NULL; int ret = AVERROR_EXIT; if (argc < 3) { fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]); exit(1); } const char *input_filename = argv[1]; const char *output_filename = argv[2]; /** Register all codecs and formats so that they can be used. */ av_register_all(); /** Open the input file for reading. */ if (open_input_file(input_filename, &input_format_context, &input_codec_context)) goto cleanup; /** Open the output file for writing. */ if (open_output_file(output_filename, input_codec_context, &output_format_context, &output_codec_context)) goto cleanup; /** Initialize the resampler to be able to convert audio sample formats. */ if (init_resampler(input_codec_context, output_codec_context, &resample_context)) goto cleanup; /** Initialize the FIFO buffer to store audio samples to be encoded. */ if (init_fifo(&fifo, output_codec_context)) goto cleanup; /** Write the header of the output file container. */ if (write_output_file_header(output_format_context)) goto cleanup; /** * Loop as long as we have input samples to read or output samples * to write; abort as soon as we have neither. */ while (1) { /** Use the encoder's desired frame size for processing. */ const int output_frame_size = output_codec_context->frame_size; int finished = 0; /** * Make sure that there is one frame worth of samples in the FIFO * buffer so that the encoder can do its work. * Since the decoder's and the encoder's frame size may differ, we * need to FIFO buffer to store as many frames worth of input samples * that they make up at least one frame worth of output samples. */ while (av_audio_fifo_size(fifo) < output_frame_size) { /** * Decode one frame worth of audio samples, convert it to the * output sample format and put it into the FIFO buffer. */ if (read_decode_convert_and_store(fifo, input_format_context, input_codec_context, output_codec_context, resample_context, &finished)) goto cleanup; /** * If we are at the end of the input file, we continue * encoding the remaining audio samples to the output file. */ if (finished) break; } /** * If we have enough samples for the encoder, we encode them. * At the end of the file, we pass the remaining samples to * the encoder. */ while (av_audio_fifo_size(fifo) >= output_frame_size || (finished && av_audio_fifo_size(fifo) > 0)) /** * Take one frame worth of audio samples from the FIFO buffer, * encode it and write it to the output file. */ if (load_encode_and_write(fifo, output_format_context, output_codec_context)) goto cleanup; /** * If we are at the end of the input file and have encoded * all remaining samples, we can exit this loop and finish. */ if (finished) { int data_written; /** Flush the encoder as it may have delayed frames. */ do { if (encode_audio_frame(NULL, output_format_context, output_codec_context, &data_written)) goto cleanup; } while (data_written); break; } } /** Write the trailer of the output file container. */ if (write_output_file_trailer(output_format_context)) goto cleanup; ret = 0; cleanup: if (fifo) av_audio_fifo_free(fifo); swr_free(&resample_context); if (output_codec_context) avcodec_close(output_codec_context); if (output_format_context) { avio_closep(&output_format_context->pb); avformat_free_context(output_format_context); } if (input_codec_context) avcodec_close(input_codec_context); if (input_format_context) avformat_close_input(&input_format_context); return ret; }
int avresample_available(AVAudioResampleContext *avr) { return av_audio_fifo_size(avr->out_fifo); }
int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, uint8_t **output, int out_plane_size, int out_samples, uint8_t **input, int in_plane_size, int in_samples) { AudioData input_buffer; AudioData output_buffer; AudioData *current_buffer; int ret, direct_output; /* reset internal buffers */ if (avr->in_buffer) { avr->in_buffer->nb_samples = 0; ff_audio_data_set_channels(avr->in_buffer, avr->in_buffer->allocated_channels); } if (avr->resample_out_buffer) { avr->resample_out_buffer->nb_samples = 0; ff_audio_data_set_channels(avr->resample_out_buffer, avr->resample_out_buffer->allocated_channels); } if (avr->out_buffer) { avr->out_buffer->nb_samples = 0; ff_audio_data_set_channels(avr->out_buffer, avr->out_buffer->allocated_channels); } av_dlog(avr, "[start conversion]\n"); /* initialize output_buffer with output data */ direct_output = output && av_audio_fifo_size(avr->out_fifo) == 0; if (output) { ret = ff_audio_data_init(&output_buffer, output, out_plane_size, avr->out_channels, out_samples, avr->out_sample_fmt, 0, "output"); if (ret < 0) return ret; output_buffer.nb_samples = 0; } if (input) { /* initialize input_buffer with input data */ ret = ff_audio_data_init(&input_buffer, input, in_plane_size, avr->in_channels, in_samples, avr->in_sample_fmt, 1, "input"); if (ret < 0) return ret; current_buffer = &input_buffer; if (avr->upmix_needed && !avr->in_convert_needed && !avr->resample_needed && !avr->out_convert_needed && direct_output && out_samples >= in_samples) { /* in some rare cases we can copy input to output and upmix directly in the output buffer */ av_dlog(avr, "[copy] %s to output\n", current_buffer->name); ret = ff_audio_data_copy(&output_buffer, current_buffer, avr->remap_point == REMAP_OUT_COPY ? &avr->ch_map_info : NULL); if (ret < 0) return ret; current_buffer = &output_buffer; } else if (avr->remap_point == REMAP_OUT_COPY && (!direct_output || out_samples < in_samples)) { /* if remapping channels during output copy, we may need to * use an intermediate buffer in order to remap before adding * samples to the output fifo */ av_dlog(avr, "[copy] %s to out_buffer\n", current_buffer->name); ret = ff_audio_data_copy(avr->out_buffer, current_buffer, &avr->ch_map_info); if (ret < 0) return ret; current_buffer = avr->out_buffer; } else if (avr->in_copy_needed || avr->in_convert_needed) { /* if needed, copy or convert input to in_buffer, and downmix if applicable */ if (avr->in_convert_needed) { ret = ff_audio_data_realloc(avr->in_buffer, current_buffer->nb_samples); if (ret < 0) return ret; av_dlog(avr, "[convert] %s to in_buffer\n", current_buffer->name); ret = ff_audio_convert(avr->ac_in, avr->in_buffer, current_buffer); if (ret < 0) return ret; } else { av_dlog(avr, "[copy] %s to in_buffer\n", current_buffer->name); ret = ff_audio_data_copy(avr->in_buffer, current_buffer, avr->remap_point == REMAP_IN_COPY ? &avr->ch_map_info : NULL); if (ret < 0) return ret; } ff_audio_data_set_channels(avr->in_buffer, avr->in_channels); if (avr->downmix_needed) { av_dlog(avr, "[downmix] in_buffer\n"); ret = ff_audio_mix(avr->am, avr->in_buffer); if (ret < 0) return ret; } current_buffer = avr->in_buffer; } } else { /* flush resampling buffer and/or output FIFO if input is NULL */ if (!avr->resample_needed) return handle_buffered_output(avr, output ? &output_buffer : NULL, NULL); current_buffer = NULL; } if (avr->resample_needed) { AudioData *resample_out; if (!avr->out_convert_needed && direct_output && out_samples > 0) resample_out = &output_buffer; else resample_out = avr->resample_out_buffer; av_dlog(avr, "[resample] %s to %s\n", current_buffer ? current_buffer->name : "null", resample_out->name); ret = ff_audio_resample(avr->resample, resample_out, current_buffer); if (ret < 0) return ret; /* if resampling did not produce any samples, just return 0 */ if (resample_out->nb_samples == 0) { av_dlog(avr, "[end conversion]\n"); return 0; } current_buffer = resample_out; } if (avr->upmix_needed) { av_dlog(avr, "[upmix] %s\n", current_buffer->name); ret = ff_audio_mix(avr->am, current_buffer); if (ret < 0) return ret; } /* if we resampled or upmixed directly to output, return here */ if (current_buffer == &output_buffer) { av_dlog(avr, "[end conversion]\n"); return current_buffer->nb_samples; } if (avr->out_convert_needed) { if (direct_output && out_samples >= current_buffer->nb_samples) { /* convert directly to output */ av_dlog(avr, "[convert] %s to output\n", current_buffer->name); ret = ff_audio_convert(avr->ac_out, &output_buffer, current_buffer); if (ret < 0) return ret; av_dlog(avr, "[end conversion]\n"); return output_buffer.nb_samples; } else { ret = ff_audio_data_realloc(avr->out_buffer, current_buffer->nb_samples); if (ret < 0) return ret; av_dlog(avr, "[convert] %s to out_buffer\n", current_buffer->name); ret = ff_audio_convert(avr->ac_out, avr->out_buffer, current_buffer); if (ret < 0) return ret; current_buffer = avr->out_buffer; } } return handle_buffered_output(avr, output ? &output_buffer : NULL, current_buffer); }
static int opus_decode_frame(OpusStreamContext *s, const uint8_t *data, int size) { int samples = s->packet.frame_duration; int redundancy = 0; int redundancy_size, redundancy_pos; int ret, i, consumed; int delayed_samples = s->delayed_samples; ret = opus_rc_init(&s->rc, data, size); if (ret < 0) return ret; /* decode the silk frame */ if (s->packet.mode == OPUS_MODE_SILK || s->packet.mode == OPUS_MODE_HYBRID) { if (!swr_is_initialized(s->swr)) { ret = opus_init_resample(s); if (ret < 0) return ret; } samples = ff_silk_decode_superframe(s->silk, &s->rc, s->silk_output, FFMIN(s->packet.bandwidth, OPUS_BANDWIDTH_WIDEBAND), s->packet.stereo + 1, silk_frame_duration_ms[s->packet.config]); if (samples < 0) { av_log(s->avctx, AV_LOG_ERROR, "Error decoding a SILK frame.\n"); return samples; } samples = swr_convert(s->swr, (uint8_t**)s->out, s->packet.frame_duration, (const uint8_t**)s->silk_output, samples); if (samples < 0) { av_log(s->avctx, AV_LOG_ERROR, "Error resampling SILK data.\n"); return samples; } av_assert2((samples & 7) == 0); s->delayed_samples += s->packet.frame_duration - samples; } else ff_silk_flush(s->silk); // decode redundancy information consumed = opus_rc_tell(&s->rc); if (s->packet.mode == OPUS_MODE_HYBRID && consumed + 37 <= size * 8) redundancy = opus_rc_p2model(&s->rc, 12); else if (s->packet.mode == OPUS_MODE_SILK && consumed + 17 <= size * 8) redundancy = 1; if (redundancy) { redundancy_pos = opus_rc_p2model(&s->rc, 1); if (s->packet.mode == OPUS_MODE_HYBRID) redundancy_size = opus_rc_unimodel(&s->rc, 256) + 2; else redundancy_size = size - (consumed + 7) / 8; size -= redundancy_size; if (size < 0) { av_log(s->avctx, AV_LOG_ERROR, "Invalid redundancy frame size.\n"); return AVERROR_INVALIDDATA; } if (redundancy_pos) { ret = opus_decode_redundancy(s, data + size, redundancy_size); if (ret < 0) return ret; ff_celt_flush(s->celt); } } /* decode the CELT frame */ if (s->packet.mode == OPUS_MODE_CELT || s->packet.mode == OPUS_MODE_HYBRID) { float *out_tmp[2] = { s->out[0], s->out[1] }; float **dst = (s->packet.mode == OPUS_MODE_CELT) ? out_tmp : s->celt_output; int celt_output_samples = samples; int delay_samples = av_audio_fifo_size(s->celt_delay); if (delay_samples) { if (s->packet.mode == OPUS_MODE_HYBRID) { av_audio_fifo_read(s->celt_delay, (void**)s->celt_output, delay_samples); for (i = 0; i < s->output_channels; i++) { s->fdsp->vector_fmac_scalar(out_tmp[i], s->celt_output[i], 1.0, delay_samples); out_tmp[i] += delay_samples; } celt_output_samples -= delay_samples; } else { av_log(s->avctx, AV_LOG_WARNING, "Spurious CELT delay samples present.\n"); av_audio_fifo_drain(s->celt_delay, delay_samples); if (s->avctx->err_recognition & AV_EF_EXPLODE) return AVERROR_BUG; } } opus_raw_init(&s->rc, data + size, size); ret = ff_celt_decode_frame(s->celt, &s->rc, dst, s->packet.stereo + 1, s->packet.frame_duration, (s->packet.mode == OPUS_MODE_HYBRID) ? 17 : 0, celt_band_end[s->packet.bandwidth]); if (ret < 0) return ret; if (s->packet.mode == OPUS_MODE_HYBRID) { int celt_delay = s->packet.frame_duration - celt_output_samples; void *delaybuf[2] = { s->celt_output[0] + celt_output_samples, s->celt_output[1] + celt_output_samples }; for (i = 0; i < s->output_channels; i++) { s->fdsp->vector_fmac_scalar(out_tmp[i], s->celt_output[i], 1.0, celt_output_samples); } ret = av_audio_fifo_write(s->celt_delay, delaybuf, celt_delay); if (ret < 0) return ret; } } else ff_celt_flush(s->celt); if (s->redundancy_idx) { for (i = 0; i < s->output_channels; i++) opus_fade(s->out[i], s->out[i], s->redundancy_output[i] + 120 + s->redundancy_idx, ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx); s->redundancy_idx = 0; } if (redundancy) { if (!redundancy_pos) { ff_celt_flush(s->celt); ret = opus_decode_redundancy(s, data + size, redundancy_size); if (ret < 0) return ret; for (i = 0; i < s->output_channels; i++) { opus_fade(s->out[i] + samples - 120 + delayed_samples, s->out[i] + samples - 120 + delayed_samples, s->redundancy_output[i] + 120, ff_celt_window2, 120 - delayed_samples); if (delayed_samples) s->redundancy_idx = 120 - delayed_samples; } } else { for (i = 0; i < s->output_channels; i++) { memcpy(s->out[i] + delayed_samples, s->redundancy_output[i], 120 * sizeof(float)); opus_fade(s->out[i] + 120 + delayed_samples, s->redundancy_output[i] + 120, s->out[i] + 120 + delayed_samples, ff_celt_window2, 120); } } } return samples; }