first commit

This commit is contained in:
2026-02-21 17:11:31 +09:00
commit 18b4338361
4001 changed files with 365464 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
* This file is part of QtAV
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 "AudioDecoder.h"
#include "AudioResampler.h"
#include "Packet.h"
#include "AVDecoder_p.h"
#include "AVCompat.h"
#include "mkid.h"
#include "factory.h"
#include "version.h"
#include "Logger.h"
namespace FAV {
class AudioDecoderFFmpegPrivate;
class AudioDecoderFFmpeg : public AudioDecoder
{
Q_OBJECT
Q_DISABLE_COPY(AudioDecoderFFmpeg)
DPTR_DECLARE_PRIVATE(AudioDecoderFFmpeg)
Q_PROPERTY(QString codecName READ codecName WRITE setCodecName NOTIFY codecNameChanged)
public:
AudioDecoderFFmpeg();
AudioDecoderId id() const Q_DECL_OVERRIDE Q_DECL_FINAL;
virtual QString description() const Q_DECL_OVERRIDE Q_DECL_FINAL {
const int patch = QTAV_VERSION_PATCH(avcodec_version());
return QStringLiteral("%1 avcodec %2.%3.%4")
.arg(patch>=100?QStringLiteral("FFmpeg"):QStringLiteral("Libav"))
.arg(QTAV_VERSION_MAJOR(avcodec_version())).arg(QTAV_VERSION_MINOR(avcodec_version())).arg(patch);
}
#if (PLAY_SYNC_FIX2)
virtual bool send(const Packet* packet) Q_DECL_OVERRIDE Q_DECL_FINAL;
virtual bool receive() Q_DECL_OVERRIDE Q_DECL_FINAL;
#endif // PLAY_SYNC_FIX2
bool decode(const Packet& packet) Q_DECL_OVERRIDE Q_DECL_FINAL;
AudioFrame frame() Q_DECL_OVERRIDE Q_DECL_FINAL;
Q_SIGNALS:
void codecNameChanged() Q_DECL_OVERRIDE Q_DECL_FINAL;
};
AudioDecoderId AudioDecoderId_FFmpeg = mkid::id32base36_6<'F','F','m','p','e','g'>::value;
FACTORY_REGISTER(AudioDecoder, FFmpeg, "FFmpeg")
class AudioDecoderFFmpegPrivate Q_DECL_FINAL: public AudioDecoderPrivate
{
public:
AudioDecoderFFmpegPrivate()
: AudioDecoderPrivate()
, frame(av_frame_alloc())
{
avcodec_register_all();
}
~AudioDecoderFFmpegPrivate() {
if (frame) {
av_frame_free(&frame);
frame = 0;
}
}
AVFrame *frame; //set once and not change
};
AudioDecoderId AudioDecoderFFmpeg::id() const
{
return AudioDecoderId_FFmpeg;
}
AudioDecoderFFmpeg::AudioDecoderFFmpeg()
: AudioDecoder(*new AudioDecoderFFmpegPrivate())
{
}
#if (PLAY_SYNC_FIX2)
bool AudioDecoderFFmpeg::send(const Packet* packet) {
return true;
}
bool AudioDecoderFFmpeg::receive() {
return true;
}
#endif // PLAY_SYNC_FIX2
bool AudioDecoderFFmpeg::decode(const Packet &packet)
{
if (!isAvailable())
return false;
DPTR_D(AudioDecoderFFmpeg);
d.decoded.clear();
int got_frame_ptr = 0;
int ret = 0;
if (packet.isEOF()) {
AVPacket eofpkt;
av_init_packet(&eofpkt);
eofpkt.data = NULL;
eofpkt.size = 0;
ret = avcodec_decode_audio4(d.codec_ctx, d.frame, &got_frame_ptr, &eofpkt);
} else {
// const AVPacket*: ffmpeg >= 1.0. no libav
ret = avcodec_decode_audio4(d.codec_ctx, d.frame, &got_frame_ptr, (AVPacket*)packet.asAVPacket());
}
d.undecoded_size = qMin(packet.data.size() - ret, packet.data.size());
if (ret == AVERROR(EAGAIN)) {
return false;
}
if (ret < 0) {
qWarning("[AudioDecoder] %s", av_err2str(ret));
return false;
}
if (!got_frame_ptr) {
qWarning("[AudioDecoder] got_frame_ptr=false. decoded: %d, un: %d", ret, d.undecoded_size);
return !packet.isEOF();
}
#if USE_AUDIO_FRAME
return true;
#endif
d.resampler->setInSampesPerChannel(d.frame->nb_samples);
if (!d.resampler->convert((const quint8**)d.frame->extended_data)) {
return false;
}
d.decoded = d.resampler->outData();
return true;
return !d.decoded.isEmpty();
}
AudioFrame AudioDecoderFFmpeg::frame()
{
DPTR_D(AudioDecoderFFmpeg);
AudioFormat fmt;
fmt.setSampleFormatFFmpeg(d.frame->format);
fmt.setChannelLayoutFFmpeg(d.frame->channel_layout);
fmt.setSampleRate(d.frame->sample_rate);
if (!fmt.isValid()) {// need more data to decode to get a frame
return AudioFrame();
}
AudioFrame f(fmt);
//av_frame_get_pkt_duration ffmpeg
f.setBits(d.frame->extended_data); // TODO: ref
f.setBytesPerLine(d.frame->linesize[0], 0); // for correct alignment
f.setSamplesPerChannel(d.frame->nb_samples);
// TODO: ffplay check AVFrame.pts, pkt_pts, last_pts+nb_samples. move to AudioFrame::from(AVFrame*)
//f.setTimestamp((double)d.frame->pkt_pts/1000.0);
f.setPTS((double)d.frame->pkt_pts/1000.0);
f.setAudioResampler(d.resampler); // TODO: remove. it's not safe if frame is shared. use a pool or detach if ref >1
return f;
}
} //namespace FAV
#include "AudioDecoderFFmpeg.moc"