static av_cold int init_audio(AVFilterContext *ctx) { BufferSourceContext *s = ctx->priv; int ret = 0; s->sample_fmt = av_get_sample_fmt(s->sample_fmt_str); if (s->sample_fmt == AV_SAMPLE_FMT_NONE) { av_log(ctx, AV_LOG_ERROR, "Invalid sample format %s.\n", s->sample_fmt_str); return AVERROR(EINVAL); } s->channel_layout = av_get_channel_layout(s->channel_layout_str); if (!s->channel_layout) { av_log(ctx, AV_LOG_ERROR, "Invalid channel layout %s.\n", s->channel_layout_str); return AVERROR(EINVAL); } if (!(s->fifo = av_fifo_alloc(sizeof(AVFrame*)))) return AVERROR(ENOMEM); if (!s->time_base.num) s->time_base = (AVRational){1, s->sample_rate}; av_log(ctx, AV_LOG_VERBOSE, "tb:%d/%d samplefmt:%s samplerate: %d " "ch layout:%s\n", s->time_base.num, s->time_base.den, s->sample_fmt_str, s->sample_rate, s->channel_layout_str); return ret; }
void emitPacket(AudioEncoder* enc, AVPacket& opacket) { auto sampleFmt = av_get_sample_fmt(enc->oparams.sampleFmt.c_str()); assert(av_sample_fmt_is_planar(sampleFmt) == 0 && "planar formats not supported"); // enc->time = enc->frame->pkt_pts > 0 ? // static_cast<std::int64_t>(enc->frame->pkt_pts * // av_q2d(enc->stream->time_base) * 1000) : 0; // enc->pts = enc->frame->pkt_pts; // Compute stream time in milliseconds if (enc->stream && opacket.pts >= 0) { enc->time = static_cast<std::int64_t>( opacket.pts * av_q2d(enc->stream->time_base) * 1000); } enc->pts = opacket.pts; assert(opacket.data); assert(opacket.size); // assert(opacket.pts >= 0); // assert(opacket.dts >= 0); AudioPacket audio(opacket.data, opacket.size, enc->outputFrameSize, enc->time); audio.source = &opacket; audio.opaque = enc; enc->emitter.emit(/*enc, */ audio); }
int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx) { char *tail; int sfmt = av_get_sample_fmt(arg); if (sfmt == AV_SAMPLE_FMT_NONE) { sfmt = strtol(arg, &tail, 0); if (*tail || (unsigned)sfmt >= AV_SAMPLE_FMT_NB) { av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg); return AVERROR(EINVAL); } } *ret = sfmt; return 0; }
int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx) { char *tail; #if 0 int sfmt = av_get_sample_fmt(arg); if (sfmt == AV_SAMPLE_FMT_NONE) { sfmt = strtol(arg, &tail, 0); if (*tail || av_get_bytes_per_sample(sfmt)<=0) { av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg); return AVERROR(EINVAL); } } *ret = sfmt; #endif return 0; }
QVariantMap MediaSink::addStream(int streamIndex, const QbCaps &streamCaps, const QVariantMap &codecParams) { QString outputFormat; if (this->supportedFormats().contains(this->m_outputFormat)) outputFormat = this->m_outputFormat; else { AVOutputFormat *format = av_guess_format(NULL, this->m_location.toStdString().c_str(), NULL); if (format) outputFormat = QString(format->name); } if (outputFormat.isEmpty()) return QVariantMap(); QVariantMap outputParams; outputParams["index"] = streamIndex; QString codec; if (codecParams.contains("codec")) { if (supportedCodecs(outputFormat, streamCaps.mimeType()) .contains(codecParams["codec"].toString())) { codec = codecParams["codec"].toString(); } else codec = this->defaultCodec(outputFormat, streamCaps.mimeType()); } else codec = this->defaultCodec(outputFormat, streamCaps.mimeType()); outputParams["codec"] = codec; QVariantMap codecDefaults = this->defaultCodecParams(codec); outputParams["codecOptions"] = codecParams.value("codecOptions", QVariantMap()); if (streamCaps.mimeType() == "audio/x-raw") { int bitRate = codecParams.value("bitRate", codecDefaults["defaultBitRate"]).toInt(); outputParams["bitRate"] = bitRate > 0? bitRate: codecDefaults["defaultBitRate"].toInt(); QbAudioCaps audioCaps(streamCaps); QString sampleFormat = QbAudioCaps::sampleFormatToString(audioCaps.format()); QStringList supportedSampleFormats = codecDefaults["supportedSampleFormats"].toStringList(); if (!supportedSampleFormats.isEmpty() && !supportedSampleFormats.contains(sampleFormat)) { QString defaultSampleFormat = codecDefaults["defaultSampleFormat"].toString(); audioCaps.format() = QbAudioCaps::sampleFormatFromString(defaultSampleFormat); audioCaps.bps() = av_get_bytes_per_sample(av_get_sample_fmt(defaultSampleFormat.toStdString().c_str())); } QVariantList supportedSampleRates = codecDefaults["supportedSampleRates"].toList(); if (!supportedSampleRates.isEmpty()) { int sampleRate = 0; int maxDiff = std::numeric_limits<int>::max(); foreach (QVariant rate, supportedSampleRates) { int diff = qAbs(audioCaps.rate() - rate.toInt()); if (diff < maxDiff) { sampleRate = rate.toInt(); if (!diff) break; maxDiff = diff; } }
AVSampleFormat getAVSampleFormat( const std::string& sampleFormat ) { return av_get_sample_fmt( sampleFormat.c_str() ); }
enum AVSampleFormat avcodec_get_sample_fmt(const char* name) { return av_get_sample_fmt(name); }
void ACapsConvertElement::iStream(const QbPacket &packet) { if (!packet.caps().isValid() || packet.caps().mimeType() != "audio/x-raw" || this->state() != ElementStatePlaying) return; // Input Format AVSampleFormat iSampleFormat = av_get_sample_fmt(packet.caps().property("format").toString().toStdString().c_str()); int iNChannels = packet.caps().property("channels").toInt(); int64_t iChannelLayout = av_get_channel_layout(packet.caps().property("layout").toString().toStdString().c_str()); int iNPlanes = av_sample_fmt_is_planar(iSampleFormat)? iNChannels: 1; int iSampleRate = packet.caps().property("rate").toInt(); int iNSamples = packet.caps().property("samples").toInt(); if (iNSamples < 1) iNSamples = 1024; bool sameMimeType = packet.caps().mimeType() == this->m_caps.mimeType(); // Output Format AVSampleFormat oSampleFormat = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("format"))? av_get_sample_fmt(this->m_caps.property("format").toString().toStdString().c_str()): iSampleFormat; int oNChannels = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("channels"))? this->m_caps.property("channels").toInt(): iNChannels; int64_t oChannelLayout = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("layout"))? av_get_channel_layout(this->m_caps.property("layout").toString().toStdString().c_str()): iChannelLayout; int oSampleRate = (sameMimeType && this->m_caps.dynamicPropertyNames().contains("rate"))? this->m_caps.property("rate").toInt(): iSampleRate; QVector<uint8_t *> iData(iNPlanes); int iLineSize; if (av_samples_fill_arrays(&iData.data()[0], &iLineSize, (const uint8_t *) packet.buffer().data(), iNChannels, iNSamples, iSampleFormat, 1) < 0) return; QbCaps caps1(packet.caps()); QbCaps caps2(this->m_curInputCaps); caps1.setProperty("samples", QVariant()); caps2.setProperty("samples", QVariant()); if (caps1 != caps2) { // create resampler context this->m_resampleContext = SwrContextPtr(swr_alloc(), this->deleteSwrContext); if (!this->m_resampleContext) return; // set options av_opt_set_int(this->m_resampleContext.data(), "in_channel_layout", iChannelLayout, 0); av_opt_set_int(this->m_resampleContext.data(), "in_sample_rate", iSampleRate, 0); av_opt_set_sample_fmt(this->m_resampleContext.data(), "in_sample_fmt", iSampleFormat, 0); av_opt_set_int(this->m_resampleContext.data(), "out_channel_layout", oChannelLayout, 0); av_opt_set_int(this->m_resampleContext.data(), "out_sample_rate", oSampleRate, 0); av_opt_set_sample_fmt(this->m_resampleContext.data(), "out_sample_fmt", oSampleFormat, 0); // initialize the resampling context if (swr_init(this->m_resampleContext.data()) < 0) return; this->m_curInputCaps = packet.caps(); } // compute destination number of samples int oNSamples = av_rescale_rnd(swr_get_delay(this->m_resampleContext.data(), iSampleRate) + iNSamples, oSampleRate, iSampleRate, AV_ROUND_UP); // buffer is going to be directly written to a rawaudio file, no alignment int oNPlanes = av_sample_fmt_is_planar(oSampleFormat)? oNChannels: 1; QVector<uint8_t *> oData(oNPlanes); int oLineSize; int oBufferSize = av_samples_get_buffer_size(&oLineSize, oNChannels, oNSamples, oSampleFormat, 1); QSharedPointer<uchar> oBuffer(new uchar[oBufferSize]); if (!oBuffer) return; if (av_samples_fill_arrays(&oData.data()[0], &oLineSize, (const uint8_t *) oBuffer.data(), oNChannels, oNSamples, oSampleFormat, 1) < 0) return; // convert to destination format if (swr_convert(this->m_resampleContext.data(), oData.data(), oNSamples, (const uint8_t **) iData.data(), iNSamples) < 0) return; const char *format = av_get_sample_fmt_name(oSampleFormat); char layout[256]; av_get_channel_layout_string(layout, sizeof(layout), oNChannels, oChannelLayout); QString caps = QString("audio/x-raw," "format=%1," "channels=%2," "rate=%3," "layout=%4," "samples=%5").arg(format) .arg(oNChannels) .arg(oSampleRate) .arg(layout) .arg(oNSamples); QbPacket oPacket(caps, oBuffer, oBufferSize); oPacket.setPts(packet.pts()); oPacket.setDuration(packet.duration()); oPacket.setTimeBase(packet.timeBase()); oPacket.setIndex(packet.index()); emit this->oStream(oPacket); }
AkPacket ConvertAudioFFmpeg::convert(const AkAudioPacket &packet, const AkCaps &oCaps) { AkAudioCaps oAudioCaps(oCaps); int64_t iSampleLayout = channelLayouts->value(packet.caps().layout(), 0); AVSampleFormat iSampleFormat = av_get_sample_fmt(AkAudioCaps::sampleFormatToString(packet.caps().format()) .toStdString().c_str()); int iSampleRate = packet.caps().rate(); int iNChannels = packet.caps().channels(); int iNSamples = packet.caps().samples(); int64_t oSampleLayout = channelLayouts->value(oAudioCaps.layout(), AV_CH_LAYOUT_STEREO); AVSampleFormat oSampleFormat = av_get_sample_fmt(AkAudioCaps::sampleFormatToString(oAudioCaps.format()) .toStdString().c_str()); int oSampleRate = oAudioCaps.rate(); int oNChannels = oAudioCaps.channels(); this->m_resampleContext = swr_alloc_set_opts(this->m_resampleContext, oSampleLayout, oSampleFormat, oSampleRate, iSampleLayout, iSampleFormat, iSampleRate, 0, NULL); if (!this->m_resampleContext) return AkPacket(); // Create input audio frame. static AVFrame iFrame; memset(&iFrame, 0, sizeof(AVFrame)); iFrame.format = iSampleFormat; iFrame.channels = iNChannels; iFrame.channel_layout = uint64_t(iSampleLayout); iFrame.sample_rate = iSampleRate; iFrame.nb_samples = iNSamples; iFrame.pts = iFrame.pkt_pts = packet.pts(); if (avcodec_fill_audio_frame(&iFrame, iFrame.channels, iSampleFormat, reinterpret_cast<const uint8_t *>(packet.buffer().constData()), packet.buffer().size(), 1) < 0) { return AkPacket(); } // Fill output audio frame. AVFrame oFrame; memset(&oFrame, 0, sizeof(AVFrame)); oFrame.format = oSampleFormat; oFrame.channels = oNChannels; oFrame.channel_layout = uint64_t(oSampleLayout); oFrame.sample_rate = oSampleRate; oFrame.nb_samples = int(swr_get_delay(this->m_resampleContext, oSampleRate)) + iFrame.nb_samples * oSampleRate / iSampleRate + 3; oFrame.pts = oFrame.pkt_pts = iFrame.pts * oSampleRate / iSampleRate; // Calculate the size of the audio buffer. int frameSize = av_samples_get_buffer_size(oFrame.linesize, oFrame.channels, oFrame.nb_samples, oSampleFormat, 1); QByteArray oBuffer(frameSize, Qt::Uninitialized); if (avcodec_fill_audio_frame(&oFrame, oFrame.channels, oSampleFormat, reinterpret_cast<const uint8_t *>(oBuffer.constData()), oBuffer.size(), 1) < 0) { return AkPacket(); } // convert to destination format if (swr_convert_frame(this->m_resampleContext, &oFrame, &iFrame) < 0) return AkPacket(); frameSize = av_samples_get_buffer_size(oFrame.linesize, oFrame.channels, oFrame.nb_samples, oSampleFormat, 1); oBuffer.resize(frameSize); AkAudioPacket oAudioPacket; oAudioPacket.caps() = oAudioCaps; oAudioPacket.caps().samples() = oFrame.nb_samples; oAudioPacket.buffer() = oBuffer; oAudioPacket.pts() = oFrame.pts; oAudioPacket.timeBase() = AkFrac(1, oAudioCaps.rate()); oAudioPacket.index() = packet.index(); oAudioPacket.id() = packet.id(); return oAudioPacket.toPacket(); }