static int filter_out(struct af_instance *af) { struct priv *p = af->priv; while (rubberband_available(p->rubber) <= 0) { const float *dummy[MP_NUM_CHANNELS] = {0}; const float **in_data = dummy; size_t in_samples = 0; if (p->pending) { if (!p->pending->samples) break; // recover from previous EOF if (p->needs_reset) { rubberband_reset(p->rubber); p->rubber_delay = 0; } p->needs_reset = false; size_t needs = rubberband_get_samples_required(p->rubber); in_data = (void *)&p->pending->planes; in_samples = MPMIN(p->pending->samples, needs); } if (p->needs_reset) break; // previous EOF p->needs_reset = !p->pending; // EOF rubberband_process(p->rubber, in_data, in_samples, p->needs_reset); p->rubber_delay += in_samples; if (!p->pending) break; mp_audio_skip_samples(p->pending, in_samples); } int out_samples = rubberband_available(p->rubber); if (out_samples > 0) { struct mp_audio *out = mp_audio_pool_get(af->out_pool, af->data, out_samples); if (!out) return -1; if (p->pending) mp_audio_copy_config(out, p->pending); float **out_data = (void *)&out->planes; out->samples = rubberband_retrieve(p->rubber, out_data, out->samples); p->rubber_delay -= out->samples * p->speed; af_add_output_frame(af, out); } int delay_samples = p->rubber_delay; if (p->pending) delay_samples += p->pending->samples; af->delay = delay_samples / (af->data->rate * p->speed); return 0; }
// Copy data from input frame to encode frame (because libavcodec wants a full // AC3 frame for encoding, while filter input frames can be smaller or larger). // Return true if the frame is complete. static bool fill_buffer(struct af_instance *af) { af_ac3enc_t *s = af->priv; af->delay = 0; if (s->pending) { int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples); s->input->samples += copy; mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy); mp_audio_skip_samples(s->pending, copy); } update_delay(af); return s->input->samples >= s->in_samples; }
// Copy data from input frame to encode frame (because libavcodec wants a full // AC3 frame for encoding, while filter input frames can be smaller or larger). // Return true if the frame is complete. static bool fill_buffer(struct af_instance *af) { af_ac3enc_t *s = af->priv; af->delay = 0; if (s->pending) { if (!mp_audio_is_writeable(s->input)) assert(s->input->samples == 0); // we can't have sent a partial frame mp_audio_realloc_min(s->input, s->in_samples); int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples); s->input->samples += copy; mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy); mp_audio_skip_samples(s->pending, copy); } update_delay(af); return s->input->samples >= s->in_samples; }
// Filter data through filter static int filter(struct af_instance* af, struct mp_audio* audio, int flags) { struct mp_audio *out = af->data; af_ac3enc_t *s = af->priv; int num_frames = (audio->samples + mp_audio_buffer_samples(s->pending)) / s->in_samples; int max_out_samples = s->out_samples * num_frames; mp_audio_realloc_min(out, max_out_samples); out->samples = 0; while (audio->samples > 0) { int ret; int consumed_pending = 0; struct mp_audio in_frame; int pending = mp_audio_buffer_samples(s->pending); if (pending == 0 && audio->samples >= s->in_samples) { in_frame = *audio; mp_audio_skip_samples(audio, s->in_samples); } else { if (pending > 0 && pending < s->in_samples) { struct mp_audio tmp = *audio; tmp.samples = MPMIN(tmp.samples, s->in_samples); mp_audio_buffer_append(s->pending, &tmp); mp_audio_skip_samples(audio, tmp.samples); } mp_audio_buffer_peek(s->pending, &in_frame); if (in_frame.samples < s->in_samples) break; consumed_pending = s->in_samples; } in_frame.samples = s->in_samples; AVFrame *frame = av_frame_alloc(); if (!frame) { MP_FATAL(af, "Could not allocate memory \n"); return -1; } frame->nb_samples = s->in_samples; frame->format = s->lavc_actx->sample_fmt; frame->channel_layout = s->lavc_actx->channel_layout; assert(in_frame.num_planes <= AV_NUM_DATA_POINTERS); frame->extended_data = frame->data; for (int n = 0; n < in_frame.num_planes; n++) frame->data[n] = in_frame.planes[n]; frame->linesize[0] = s->in_samples * audio->sstride; int ok; ret = avcodec_encode_audio2(s->lavc_actx, &s->pkt, frame, &ok); av_frame_free(&frame); if (ret < 0 || !ok) { MP_FATAL(af, "Encode failed.\n"); return -1; } mp_audio_buffer_skip(s->pending, consumed_pending); MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n", s->pkt.size, mp_audio_buffer_samples(s->pending)); int frame_size = s->pkt.size; int header_len = 0; char hdr[8]; if (s->cfg_add_iec61937_header && s->pkt.size > 5) { int bsmod = s->pkt.data[5] & 0x7; int len = frame_size; frame_size = AC3_FRAME_SIZE * 2 * 2; header_len = 8; AV_WB16(hdr, 0xF872); // iec 61937 syncword 1 AV_WB16(hdr + 2, 0x4E1F); // iec 61937 syncword 2 hdr[4] = bsmod; // bsmod hdr[5] = 0x01; // data-type ac3 AV_WB16(hdr + 6, len << 3); // number of bits in payload } size_t max_size = (max_out_samples - out->samples) * out->sstride; if (frame_size > max_size) abort(); char *buf = (char *)out->planes[0] + out->samples * out->sstride; memcpy(buf, hdr, header_len); memcpy(buf + header_len, s->pkt.data, s->pkt.size); memset(buf + header_len + s->pkt.size, 0, frame_size - (header_len + s->pkt.size)); out->samples += frame_size / out->sstride; } mp_audio_buffer_append(s->pending, audio); *audio = *out; return 0; }
// Filter len bytes of input, put result into outbuf. static int filter_n_bytes(struct dec_audio *da, struct mp_audio_buffer *outbuf, int len) { bool format_change = false; int error = 0; assert(len > 0); // would break EOF logic below while (mp_audio_buffer_samples(da->decode_buffer) < len) { // Check for a format change struct mp_audio config; mp_audio_buffer_get_format(da->decode_buffer, &config); format_change = !mp_audio_config_equals(&da->decoded, &config); if (format_change) { error = AD_EOF; // drain remaining data left in the current buffer break; } if (da->decoded.samples > 0) { int copy = MPMIN(da->decoded.samples, len); struct mp_audio append = da->decoded; append.samples = copy; mp_audio_buffer_append(da->decode_buffer, &append); mp_audio_skip_samples(&da->decoded, copy); da->pts_offset += copy; continue; } error = da->ad_driver->decode_packet(da); if (error < 0) break; } if (error == AD_WAIT) return error; // Filter struct mp_audio filter_data; mp_audio_buffer_peek(da->decode_buffer, &filter_data); filter_data.rate = da->afilter->input.rate; // due to playback speed change len = MPMIN(filter_data.samples, len); filter_data.samples = len; bool eof = error == AD_EOF && filter_data.samples == 0; if (af_filter(da->afilter, &filter_data, eof ? AF_FILTER_FLAG_EOF : 0) < 0) return AD_ERR; mp_audio_buffer_append(outbuf, &filter_data); if (error == AD_EOF && filter_data.samples > 0) error = 0; // don't end playback yet // remove processed data from decoder buffer: mp_audio_buffer_skip(da->decode_buffer, len); // if format was changed, and all data was drained, execute the format change if (format_change && eof) { error = AD_NEW_FMT; if (!reinit_audio_buffer(da)) error = AD_ERR; // switch to invalid format } return error; }