AudioFrame AudioFrame::to(const AudioFormat &fmt) const { if (!isValid() || !constBits(0)) return AudioFrame(); //if (fmt == format()) // return clone(); //FIXME: clone a frame from ffmpeg is not enough? Q_D(const AudioFrame); // TODO: use a pool AudioResampler *conv = d->conv; QScopedPointer<AudioResampler> c; if (!conv) { conv = AudioResampler::create(AudioResamplerId_FF); if (!conv) conv = AudioResampler::create(AudioResamplerId_Libav); if (!conv) { qWarning("no audio resampler is available"); return AudioFrame(); } c.reset(conv); } conv->setInAudioFormat(format()); conv->setOutAudioFormat(fmt); //conv->prepare(); // already called in setIn/OutFormat conv->setInSampesPerChannel(samplesPerChannel()); //TODO if (!conv->convert((const quint8**)d->planes.constData())) { qWarning() << "AudioFrame::to error: " << format() << "=>" << fmt; return AudioFrame(); } AudioFrame f(conv->outData(), fmt); f.setSamplesPerChannel(conv->outSamplesPerChannel()); f.setTimestamp(timestamp()); f.d_ptr->metadata = d->metadata; // need metadata? return f; }
AudioFrame AudioFrame::clone() const { Q_D(const AudioFrame); if (!d->format.isValid()) return AudioFrame(); AudioFrame f(QByteArray(), d->format); f.setSamplesPerChannel(samplesPerChannel()); f.allocate(); // TODO: Frame.planes(), bytesPerLines() int nb_planes = f.planeCount(); QVector<uchar*> dst(nb_planes); for (int i = 0; i < nb_planes; ++i) { dst[i] = f.bits(i); } av_samples_copy(dst.data(), d->planes.data(), 0, 0, samplesPerChannel(), d->format.channels(), (AVSampleFormat)d->format.sampleFormatFFmpeg()); return f; }
AudioFrame AudioFrame::clone() const { Q_D(const AudioFrame); if (d->format.sampleFormatFFmpeg() == AV_SAMPLE_FMT_NONE || d->format.channels() <= 0) return AudioFrame(); if (d->samples_per_ch <= 0 || bytesPerLine(0) <= 0) return AudioFrame(format()); QByteArray buf(bytesPerLine()*planeCount(), 0); AudioFrame f(buf, d->format); f.setSamplesPerChannel(samplesPerChannel()); char *dst = buf.data(); //must before buf is shared, otherwise data will be detached. for (int i = 0; i < f.planeCount(); ++i) { const int plane_size = f.bytesPerLine(i); memcpy(dst, f.constBits(i), plane_size); dst += plane_size; } f.setTimestamp(timestamp()); // meta data? return f; }