bool CActiveAEBufferPoolResample::ResampleBuffers(unsigned int timestamp) { bool busy = false; CSampleBuffer *in; if (!m_resampler) { if (m_changeResampler) { ChangeResampler(); return true; } while(!m_inputSamples.empty()) { in = m_inputSamples.front(); m_inputSamples.pop_front(); in->timestamp = timestamp; m_outputSamples.push_back(in); busy = true; } } else if (m_procSample || !m_freeSamples.empty()) { // GetBufferedSamples is not accurate because of rounding errors int out_samples = m_resampler->GetBufferedSamples(); int free_samples; if (m_procSample) free_samples = m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples; else free_samples = m_format.m_frames; bool skipInput = false; // avoid that ffmpeg resample buffer grows too large if (out_samples > free_samples * 2 && !m_empty) skipInput = true; bool hasInput = !m_inputSamples.empty(); if (hasInput || skipInput || m_drain || m_changeResampler) { if (!m_procSample) { m_procSample = GetFreeBuffer(); } if (hasInput && !skipInput && !m_changeResampler) { in = m_inputSamples.front(); m_inputSamples.pop_front(); } else in = NULL; int start = m_procSample->pkt->nb_samples * m_procSample->pkt->bytes_per_sample * m_procSample->pkt->config.channels / m_procSample->pkt->planes; for(int i=0; i<m_procSample->pkt->planes; i++) { m_planes[i] = m_procSample->pkt->data[i] + start; } out_samples = m_resampler->Resample(m_planes, m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples, in ? in->pkt->data : NULL, in ? in->pkt->nb_samples : 0, m_resampleRatio); m_procSample->pkt->nb_samples += out_samples; busy = true; m_empty = (out_samples == 0); if ((m_drain || m_changeResampler) && m_empty) { if (m_fillPackets && m_procSample->pkt->nb_samples != 0) { // pad with zero start = m_procSample->pkt->nb_samples * m_procSample->pkt->bytes_per_sample * m_procSample->pkt->config.channels / m_procSample->pkt->planes; for(int i=0; i<m_procSample->pkt->planes; i++) { memset(m_procSample->pkt->data[i]+start, 0, m_procSample->pkt->linesize-start); } } m_procSample->timestamp = timestamp; // check if draining is finished if (m_drain && m_procSample->pkt->nb_samples == 0) { m_procSample->Return(); busy = false; } else m_outputSamples.push_back(m_procSample); m_procSample = NULL; if (m_changeResampler) ChangeResampler(); } // some methods like encode require completely filled packets else if (!m_fillPackets || (m_procSample->pkt->nb_samples == m_procSample->pkt->max_nb_samples)) { m_procSample->timestamp = timestamp; m_outputSamples.push_back(m_procSample); m_procSample = NULL; } if (in) in->Return(); } } return busy; }
bool CActiveAEBufferPoolResample::ResampleBuffers(int64_t timestamp) { bool busy = false; CSampleBuffer *in; if (!m_resampler) { if (m_changeDSP || m_changeResampler) { if (m_changeDSP) ChangeAudioDSP(); if (m_changeResampler) ChangeResampler(); return true; } while(!m_inputSamples.empty()) { in = m_inputSamples.front(); m_inputSamples.pop_front(); if (timestamp) { in->timestamp = timestamp; } m_outputSamples.push_back(in); busy = true; } } else if (m_procSample || !m_freeSamples.empty()) { int free_samples; if (m_procSample) free_samples = m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples; else free_samples = m_format.m_frames; bool skipInput = false; // avoid that ffmpeg resample buffer grows too large if (!m_resampler->WantsNewSamples(free_samples) && !m_empty) skipInput = true; bool hasInput = !m_inputSamples.empty(); if (hasInput || skipInput || m_drain || m_changeResampler || m_changeDSP) { if (!m_procSample) { m_procSample = GetFreeBuffer(); } if (hasInput && !skipInput && !m_changeResampler && !m_changeDSP) { in = m_inputSamples.front(); m_inputSamples.pop_front(); } else in = NULL; /* * DSP need always a available input packet! To pass it step by step * over all enabled addons and processing segments. */ if (m_useDSP && in) { if (!m_dspSample) m_dspSample = m_dspBuffer->GetFreeBuffer(); if (m_dspSample && m_processor->Process(in, m_dspSample)) { m_dspSample->timestamp = in->timestamp; in->Return(); in = m_dspSample; m_dspSample = NULL; } else { in->Return(); in = NULL; } } int start = m_procSample->pkt->nb_samples * m_procSample->pkt->bytes_per_sample * m_procSample->pkt->config.channels / m_procSample->pkt->planes; for(int i=0; i<m_procSample->pkt->planes; i++) { m_planes[i] = m_procSample->pkt->data[i] + start; } int out_samples = m_resampler->Resample(m_planes, m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples, in ? in->pkt->data : NULL, in ? in->pkt->nb_samples : 0, m_resampleRatio); // in case of error, trigger re-create of resampler if (out_samples < 0) { out_samples = 0; m_changeResampler = true; } m_procSample->pkt->nb_samples += out_samples; busy = true; m_empty = (out_samples == 0); if (in) { if (!timestamp) { if (in->timestamp) m_lastSamplePts = in->timestamp; else in->pkt_start_offset = 0; } else { m_lastSamplePts = timestamp; in->pkt_start_offset = 0; } // pts of last sample we added to the buffer m_lastSamplePts += (in->pkt->nb_samples-in->pkt_start_offset) * 1000 / m_format.m_sampleRate; } // calculate pts for last sample in m_procSample int bufferedSamples = m_resampler->GetBufferedSamples(); m_procSample->pkt_start_offset = m_procSample->pkt->nb_samples; m_procSample->timestamp = m_lastSamplePts - bufferedSamples * 1000 / m_format.m_sampleRate; if ((m_drain || m_changeResampler || m_changeDSP) && m_empty) { if (m_fillPackets && m_procSample->pkt->nb_samples != 0) { // pad with zero start = m_procSample->pkt->nb_samples * m_procSample->pkt->bytes_per_sample * m_procSample->pkt->config.channels / m_procSample->pkt->planes; for(int i=0; i<m_procSample->pkt->planes; i++) { memset(m_procSample->pkt->data[i]+start, 0, m_procSample->pkt->linesize-start); } } // check if draining is finished if (m_drain && m_procSample->pkt->nb_samples == 0) { m_procSample->Return(); busy = false; } else m_outputSamples.push_back(m_procSample); m_procSample = NULL; if (m_changeDSP) ChangeAudioDSP(); if (m_changeResampler) ChangeResampler(); } // some methods like encode require completely filled packets else if (!m_fillPackets || (m_procSample->pkt->nb_samples == m_procSample->pkt->max_nb_samples)) { m_outputSamples.push_back(m_procSample); m_procSample = NULL; } if (in) in->Return(); } } return busy; }
bool CActiveAEBufferPoolAtempo::ProcessBuffers() { bool busy = false; CSampleBuffer *in; if (!m_pTempoFilter->IsActive()) { if (m_changeFilter) { if (m_changeFilter) ChangeFilter(); return true; } while(!m_inputSamples.empty()) { in = m_inputSamples.front(); m_inputSamples.pop_front(); m_outputSamples.push_back(in); busy = true; } } else if (m_procSample || !m_freeSamples.empty()) { int free_samples; if (m_procSample) free_samples = m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples; else free_samples = m_format.m_frames; bool skipInput = false; // avoid that bufferscr grows too large if (!m_pTempoFilter->NeedData()) skipInput = true; bool hasInput = !m_inputSamples.empty(); if (hasInput || skipInput || m_drain || m_changeFilter) { if (!m_procSample) { m_procSample = GetFreeBuffer(); } if (hasInput && !skipInput && !m_changeFilter) { in = m_inputSamples.front(); m_inputSamples.pop_front(); } else in = nullptr; int start = m_procSample->pkt->nb_samples * m_procSample->pkt->bytes_per_sample * m_procSample->pkt->config.channels / m_procSample->pkt->planes; for (int i=0; i<m_procSample->pkt->planes; i++) { m_planes[i] = m_procSample->pkt->data[i] + start; } int out_samples = m_pTempoFilter->ProcessFilter(m_planes, m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples, in ? in->pkt->data : nullptr, in ? in->pkt->nb_samples : 0, in ? in->pkt->linesize * in->pkt->planes : 0); // in case of error, trigger re-create of filter if (out_samples < 0) { out_samples = 0; m_changeFilter = true; } m_procSample->pkt->nb_samples += out_samples; busy = true; m_empty = m_pTempoFilter->IsEof(); if (in) { if (in->timestamp) m_lastSamplePts = in->timestamp; else in->pkt_start_offset = 0; // pts of last sample we added to the buffer m_lastSamplePts += (in->pkt->nb_samples-in->pkt_start_offset) * 1000 / m_format.m_sampleRate; } // calculate pts for last sample in m_procSample int bufferedSamples = m_pTempoFilter->GetBufferedSamples(); m_procSample->pkt_start_offset = m_procSample->pkt->nb_samples; m_procSample->timestamp = m_lastSamplePts - bufferedSamples * 1000 / m_format.m_sampleRate; if ((m_drain || m_changeFilter) && m_empty) { if (m_fillPackets && m_procSample->pkt->nb_samples != 0) { // pad with zero start = m_procSample->pkt->nb_samples * m_procSample->pkt->bytes_per_sample * m_procSample->pkt->config.channels / m_procSample->pkt->planes; for (int i=0; i<m_procSample->pkt->planes; i++) { memset(m_procSample->pkt->data[i]+start, 0, m_procSample->pkt->linesize-start); } } // check if draining is finished if (m_drain && m_procSample->pkt->nb_samples == 0) { m_procSample->Return(); busy = false; } else m_outputSamples.push_back(m_procSample); m_procSample = nullptr; if (m_changeFilter) { ChangeFilter(); } } // some methods like encode require completely filled packets else if (!m_fillPackets || (m_procSample->pkt->nb_samples == m_procSample->pkt->max_nb_samples)) { m_outputSamples.push_back(m_procSample); m_procSample = nullptr; } if (in) in->Return(); } } return busy; }
bool CActiveAEBufferPoolResample::ResampleBuffers(int64_t timestamp) { bool busy = false; CSampleBuffer *in; if (!m_resampler) { if (m_changeResampler) { ChangeResampler(); return true; } while(!m_inputSamples.empty()) { in = m_inputSamples.front(); m_inputSamples.pop_front(); if (timestamp) { in->timestamp = timestamp; in->clockId = -1; } m_outputSamples.push_back(in); busy = true; } } else if (m_procSample || !m_freeSamples.empty()) { int free_samples; if (m_procSample) free_samples = m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples; else free_samples = m_format.m_frames; bool skipInput = false; // avoid that ffmpeg resample buffer grows too large if (!m_resampler->WantsNewSamples(free_samples) && !m_empty) skipInput = true; bool hasInput = !m_inputSamples.empty(); if (hasInput || skipInput || m_drain || m_changeResampler) { if (!m_procSample) { m_procSample = GetFreeBuffer(); } if (hasInput && !skipInput && !m_changeResampler) { in = m_inputSamples.front(); m_inputSamples.pop_front(); } else in = NULL; int start = m_procSample->pkt->nb_samples * m_procSample->pkt->bytes_per_sample * m_procSample->pkt->config.channels / m_procSample->pkt->planes; for(int i=0; i<m_procSample->pkt->planes; i++) { m_planes[i] = m_procSample->pkt->data[i] + start; } int out_samples = m_resampler->Resample(m_planes, m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples, in ? in->pkt->data : NULL, in ? in->pkt->nb_samples : 0, m_resampleRatio); m_procSample->pkt->nb_samples += out_samples; busy = true; m_empty = (out_samples == 0); if (in) { if (!timestamp) { m_lastSamplePts = in->timestamp; m_procSample->clockId = in->clockId; } else { m_lastSamplePts = timestamp; in->pkt_start_offset = 0; m_procSample->clockId = -1; } // pts of last sample we added to the buffer m_lastSamplePts += (in->pkt->nb_samples-in->pkt_start_offset)/m_format.m_sampleRate * 1000; } // calculate pts for last sample in m_procSample int bufferedSamples = m_resampler->GetBufferedSamples(); m_procSample->pkt_start_offset = m_procSample->pkt->nb_samples; m_procSample->timestamp = m_lastSamplePts - bufferedSamples/m_format.m_sampleRate*1000; if ((m_drain || m_changeResampler) && m_empty) { if (m_fillPackets && m_procSample->pkt->nb_samples != 0) { // pad with zero start = m_procSample->pkt->nb_samples * m_procSample->pkt->bytes_per_sample * m_procSample->pkt->config.channels / m_procSample->pkt->planes; for(int i=0; i<m_procSample->pkt->planes; i++) { memset(m_procSample->pkt->data[i]+start, 0, m_procSample->pkt->linesize-start); } } // check if draining is finished if (m_drain && m_procSample->pkt->nb_samples == 0) { m_procSample->Return(); busy = false; } else m_outputSamples.push_back(m_procSample); m_procSample = NULL; if (m_changeResampler) ChangeResampler(); } // some methods like encode require completely filled packets else if (!m_fillPackets || (m_procSample->pkt->nb_samples == m_procSample->pkt->max_nb_samples)) { m_outputSamples.push_back(m_procSample); m_procSample = NULL; } if (in) in->Return(); } } return busy; }