/****************************************************************************** QtAV: Multimedia framework based on Qt and FFmpeg Copyright (C) 2012-2016 Wang Bin * This file is part of QtAV (from 2015) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ******************************************************************************/ #include "AudioEncoder.h" #if !(REMOVE_AV_ENCODER) #include "AVEncoder_p.h" #include "AVCompat.h" #include "mkid.h" #include "factory.h" #include "version.h" #include "Logger.h" /*! * options (properties) are from libavcodec/options_table.h * enum name here must convert to lower case to fit the names in avcodec. done in AVEncoder.setOptions() * Don't use lower case here because the value name may be "default" in avcodec which is a keyword of C++ */ namespace FAV { class AudioEncoderFFmpegPrivate; class AudioEncoderFFmpeg Q_DECL_FINAL: public AudioEncoder { DPTR_DECLARE_PRIVATE(AudioEncoderFFmpeg) public: AudioEncoderFFmpeg(); AudioEncoderId id() const Q_DECL_OVERRIDE; bool encode(const AudioFrame &frame = AudioFrame()) Q_DECL_OVERRIDE; }; static const AudioEncoderId AudioEncoderId_FFmpeg = mkid::id32base36_6<'F', 'F', 'm', 'p', 'e', 'g'>::value; FACTORY_REGISTER(AudioEncoder, FFmpeg, "FFmpeg") class AudioEncoderFFmpegPrivate Q_DECL_FINAL: public AudioEncoderPrivate { public: AudioEncoderFFmpegPrivate() : AudioEncoderPrivate() , frame_size(0) { avcodec_register_all(); // NULL: codec-specific defaults won't be initialized, which may result in suboptimal default settings (this is important mainly for encoders, e.g. libx264). avctx = avcodec_alloc_context3(NULL); } bool open() Q_DECL_OVERRIDE; bool close() Q_DECL_OVERRIDE; int frame_size; // used if avctx->frame_size == 0 QByteArray buffer; }; bool AudioEncoderFFmpegPrivate::open() { if (codec_name.isEmpty()) { // copy ctx from muxer by copyAVCodecContext AVCodec *codec = avcodec_find_encoder(avctx->codec_id); AV_ENSURE_OK(avcodec_open2(avctx, codec, &dict), false); return true; } AVCodec *codec = avcodec_find_encoder_by_name(codec_name.toUtf8().constData()); if (!codec) { const AVCodecDescriptor* cd = avcodec_descriptor_get_by_name(codec_name.toUtf8().constData()); if (cd) { codec = avcodec_find_encoder(cd->id); } } if (!codec) { qWarning() << "Can not find encoder for codec " << codec_name; return false; } if (avctx) { avcodec_free_context(&avctx); avctx = 0; } avctx = avcodec_alloc_context3(codec); // reset format_used to user defined format. important to update default format if format is invalid format_used = format; if (format.sampleRate() <= 0) { if (codec->supported_samplerates) { qDebug("use first supported sample rate: %d", codec->supported_samplerates[0]); format_used.setSampleRate(codec->supported_samplerates[0]); } else { qWarning("sample rate and supported sample rate are not set. use 44100"); format_used.setSampleRate(44100); } } if (format.sampleFormat() == AudioFormat::SampleFormat_Unknown) { if (codec->sample_fmts) { qDebug("use first supported sample format: %d", codec->sample_fmts[0]); format_used.setSampleFormatFFmpeg((int)codec->sample_fmts[0]); } else { qWarning("sample format and supported sample format are not set. use s16"); format_used.setSampleFormat(AudioFormat::SampleFormat_Signed16); } } if (format.channelLayout() == AudioFormat::ChannelLayout_Unsupported) { if (codec->channel_layouts) { char cl[128]; av_get_channel_layout_string(cl, sizeof(cl), -1, codec->channel_layouts[0]); //TODO: ff version qDebug("use first supported channel layout: %s", cl); format_used.setChannelLayoutFFmpeg((qint64)codec->channel_layouts[0]); } else { qWarning("channel layout and supported channel layout are not set. use stereo"); format_used.setChannelLayout(AudioFormat::ChannelLayout_Stereo); } } avctx->sample_fmt = (AVSampleFormat)format_used.sampleFormatFFmpeg(); avctx->channel_layout = format_used.channelLayoutFFmpeg(); avctx->channels = format_used.channels(); avctx->sample_rate = format_used.sampleRate(); avctx->bits_per_raw_sample = format_used.bytesPerSample()*8; /// set the time base. TODO avctx->time_base.num = 1; avctx->time_base.den = format_used.sampleRate(); avctx->bit_rate = bit_rate; qDebug() << format_used; /** Allow the use of the experimental AAC encoder */ avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; av_dict_set(&dict, "strict", "-2", 0); //aac, vorbis applyOptionsForContext(); // avctx->frame_size will be set in avcodec_open2 AV_ENSURE_OK(avcodec_open2(avctx, codec, &dict), false); // from mpv ao_lavc int pcm_hack = 0; int buffer_size = 0; frame_size = avctx->frame_size; if (frame_size <= 1) pcm_hack = av_get_bits_per_sample(avctx->codec_id)/8; if (pcm_hack) { frame_size = 16384; // "enough" buffer_size = frame_size*pcm_hack*format_used.channels()*2+200; } else { buffer_size = frame_size*format_used.bytesPerSample()*format_used.channels()*2+200; } if (buffer_size < FF_MIN_BUFFER_SIZE) buffer_size = FF_MIN_BUFFER_SIZE; buffer.resize(buffer_size); return true; } bool AudioEncoderFFmpegPrivate::close() { AV_ENSURE_OK(avcodec_close(avctx), false); return true; } AudioEncoderFFmpeg::AudioEncoderFFmpeg() : AudioEncoder(*new AudioEncoderFFmpegPrivate()) { } AudioEncoderId AudioEncoderFFmpeg::id() const { return AudioEncoderId_FFmpeg; } bool AudioEncoderFFmpeg::encode(const AudioFrame &frame) { DPTR_D(AudioEncoderFFmpeg); AVFrame *f = NULL; if (frame.isValid()) { f = av_frame_alloc(); const AudioFormat fmt(frame.format()); f->format = fmt.sampleFormatFFmpeg(); f->channel_layout = fmt.channelLayoutFFmpeg(); // f->channels = fmt.channels(); //remove? not availale in libav9 // must be (not the last frame) exactly frame_size unless CODEC_CAP_VARIABLE_FRAME_SIZE is set (frame_size==0) // TODO: mpv use pcmhack for avctx.frame_size==0. can we use input frame.samplesPerChannel? f->nb_samples = d.frame_size; /// f->quality = d.avctx->global_quality; //TODO // TODO: record last pts. mpv compute pts internally and also use playback time f->pts = int64_t(frame.timestamp()*fmt.sampleRate()); // TODO // pts is set in muxer const int nb_planes = frame.planeCount(); // bytes between 2 samples on a plane. TODO: add to AudioFormat? what about bytesPerFrame? const int sample_stride = fmt.isPlanar() ? fmt.bytesPerSample() : fmt.bytesPerSample()*fmt.channels(); for (int i = 0; i < nb_planes; ++i) { f->linesize[i] = f->nb_samples * sample_stride;// frame.bytesPerLine(i); // f->extended_data[i] = (uint8_t*)frame.constBits(i); } } AVPacket pkt; av_init_packet(&pkt); pkt.data = (uint8_t*)d.buffer.constData(); //NULL pkt.size = d.buffer.size(); //0 int got_packet = 0; int ret = avcodec_encode_audio2(d.avctx, &pkt, f, &got_packet); av_frame_free(&f); if (ret < 0) { //qWarning("error avcodec_encode_audio2: %s" ,av_err2str(ret)); //av_packet_unref(&pkt); //FIXME return false; //false } if (!got_packet) { qWarning("no packet got"); d.packet = Packet(); // invalid frame means eof return frame.isValid(); } // qDebug("enc avpkt.pts: %lld, dts: %lld.", pkt.pts, pkt.dts); d.packet = Packet::fromAVPacket(&pkt, av_q2d(d.avctx->time_base)); // qDebug("enc packet.pts: %.3f, dts: %.3f.", d.packet.pts, d.packet.dts); return true; } } //namespace FAV #endif // #if !(REMOVE_AV_ENCODER)