forked from bartvdbraak/blender
Audaspace: add support for latest ffmpeg.
This commit is contained in:
parent
528dc6440b
commit
dd2e187344
2
extern/audaspace/plugins/ffmpeg/FFMPEG.cpp
vendored
2
extern/audaspace/plugins/ffmpeg/FFMPEG.cpp
vendored
@ -23,7 +23,9 @@ AUD_NAMESPACE_BEGIN
|
||||
|
||||
FFMPEG::FFMPEG()
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 58
|
||||
av_register_all();
|
||||
#endif
|
||||
}
|
||||
|
||||
void FFMPEG::registerPlugin()
|
||||
|
124
extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
vendored
124
extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
vendored
@ -22,37 +22,37 @@
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avio.h>
|
||||
#include <libavutil/avutil.h>
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 58
|
||||
#define FFMPEG_OLD_CODE
|
||||
#endif
|
||||
|
||||
int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
|
||||
{
|
||||
AVFrame* frame = nullptr;
|
||||
int buf_size = buffer.getSize();
|
||||
int buf_pos = 0;
|
||||
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
int got_frame;
|
||||
int read_length;
|
||||
uint8_t* orig_data = packet.data;
|
||||
int orig_size = packet.size;
|
||||
|
||||
int buf_size = buffer.getSize();
|
||||
int buf_pos = 0;
|
||||
|
||||
while(packet.size > 0)
|
||||
{
|
||||
got_frame = 0;
|
||||
|
||||
if(!frame)
|
||||
frame = av_frame_alloc();
|
||||
else
|
||||
av_frame_unref(frame);
|
||||
|
||||
read_length = avcodec_decode_audio4(m_codecCtx, frame, &got_frame, &packet);
|
||||
read_length = avcodec_decode_audio4(m_codecCtx, m_frame, &got_frame, &packet);
|
||||
if(read_length < 0)
|
||||
break;
|
||||
|
||||
if(got_frame)
|
||||
{
|
||||
int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, frame->nb_samples, m_codecCtx->sample_fmt, 1);
|
||||
int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1);
|
||||
|
||||
if(buf_size - buf_pos < data_size)
|
||||
{
|
||||
@ -62,18 +62,18 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
|
||||
|
||||
if(m_tointerleave)
|
||||
{
|
||||
int single_size = data_size / m_codecCtx->channels / frame->nb_samples;
|
||||
int single_size = data_size / m_codecCtx->channels / m_frame->nb_samples;
|
||||
for(int channel = 0; channel < m_codecCtx->channels; channel++)
|
||||
{
|
||||
for(int i = 0; i < frame->nb_samples; i++)
|
||||
for(int i = 0; i < m_frame->nb_samples; i++)
|
||||
{
|
||||
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
|
||||
frame->data[channel] + i * single_size, single_size);
|
||||
m_frame->data[channel] + i * single_size, single_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos, frame->data[0], data_size);
|
||||
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos, m_frame->data[0], data_size);
|
||||
|
||||
buf_pos += data_size;
|
||||
}
|
||||
@ -83,7 +83,42 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
|
||||
|
||||
packet.data = orig_data;
|
||||
packet.size = orig_size;
|
||||
av_free(frame);
|
||||
#else
|
||||
avcodec_send_packet(m_codecCtx, &packet);
|
||||
|
||||
while(true)
|
||||
{
|
||||
auto ret = avcodec_receive_frame(m_codecCtx, m_frame);
|
||||
|
||||
if(ret != 0)
|
||||
break;
|
||||
|
||||
int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1);
|
||||
|
||||
if(buf_size - buf_pos < data_size)
|
||||
{
|
||||
buffer.resize(buf_size + data_size, true);
|
||||
buf_size += data_size;
|
||||
}
|
||||
|
||||
if(m_tointerleave)
|
||||
{
|
||||
int single_size = data_size / m_codecCtx->channels / m_frame->nb_samples;
|
||||
for(int channel = 0; channel < m_codecCtx->channels; channel++)
|
||||
{
|
||||
for(int i = 0; i < m_frame->nb_samples; i++)
|
||||
{
|
||||
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
|
||||
m_frame->data[channel] + i * single_size, single_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos, m_frame->data[0], data_size);
|
||||
|
||||
buf_pos += data_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
return buf_pos;
|
||||
}
|
||||
@ -101,7 +136,11 @@ void FFMPEGReader::init()
|
||||
|
||||
for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
|
||||
{
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
if((m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
#else
|
||||
if((m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
#endif
|
||||
&& (m_stream < 0))
|
||||
{
|
||||
m_stream=i;
|
||||
@ -112,12 +151,34 @@ void FFMPEGReader::init()
|
||||
if(m_stream == -1)
|
||||
AUD_THROW(FileException, "File couldn't be read, no audio stream found by ffmpeg.");
|
||||
|
||||
m_codecCtx = m_formatCtx->streams[m_stream]->codec;
|
||||
|
||||
// get a decoder and open it
|
||||
AVCodec* aCodec = avcodec_find_decoder(m_codecCtx->codec_id);
|
||||
#ifndef FFMPEG_OLD_CODE
|
||||
AVCodec* aCodec = avcodec_find_decoder(m_formatCtx->streams[m_stream]->codecpar->codec_id);
|
||||
|
||||
if(!aCodec)
|
||||
AUD_THROW(FileException, "File couldn't be read, no decoder found with ffmpeg.");
|
||||
#endif
|
||||
|
||||
m_frame = av_frame_alloc();
|
||||
|
||||
if(!m_frame)
|
||||
AUD_THROW(FileException, "File couldn't be read, ffmpeg frame couldn't be allocated.");
|
||||
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
m_codecCtx = m_formatCtx->streams[m_stream]->codec;
|
||||
|
||||
AVCodec* aCodec = avcodec_find_decoder(m_codecCtx->codec_id);
|
||||
#else
|
||||
m_codecCtx = avcodec_alloc_context3(aCodec);
|
||||
#endif
|
||||
|
||||
if(!m_codecCtx)
|
||||
AUD_THROW(FileException, "File couldn't be read, ffmpeg context couldn't be allocated.");
|
||||
|
||||
#ifndef FFMPEG_OLD_CODE
|
||||
if(avcodec_parameters_to_context(m_codecCtx, m_formatCtx->streams[m_stream]->codecpar) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be read, ffmpeg decoder parameters couldn't be copied to decoder context.");
|
||||
#endif
|
||||
|
||||
if(avcodec_open2(m_codecCtx, aCodec, nullptr) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be read, ffmpeg codec couldn't be opened.");
|
||||
@ -157,6 +218,8 @@ void FFMPEGReader::init()
|
||||
FFMPEGReader::FFMPEGReader(std::string filename) :
|
||||
m_pkgbuf(),
|
||||
m_formatCtx(nullptr),
|
||||
m_codecCtx(nullptr),
|
||||
m_frame(nullptr),
|
||||
m_aviocontext(nullptr),
|
||||
m_membuf(nullptr)
|
||||
{
|
||||
@ -177,12 +240,14 @@ FFMPEGReader::FFMPEGReader(std::string filename) :
|
||||
|
||||
FFMPEGReader::FFMPEGReader(std::shared_ptr<Buffer> buffer) :
|
||||
m_pkgbuf(),
|
||||
m_codecCtx(nullptr),
|
||||
m_frame(nullptr),
|
||||
m_membuffer(buffer),
|
||||
m_membufferpos(0)
|
||||
{
|
||||
m_membuf = reinterpret_cast<data_t*>(av_malloc(FF_MIN_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE));
|
||||
m_membuf = reinterpret_cast<data_t*>(av_malloc(AV_INPUT_BUFFER_MIN_SIZE + AV_INPUT_BUFFER_PADDING_SIZE));
|
||||
|
||||
m_aviocontext = avio_alloc_context(m_membuf, FF_MIN_BUFFER_SIZE, 0, this, read_packet, nullptr, seek_packet);
|
||||
m_aviocontext = avio_alloc_context(m_membuf, AV_INPUT_BUFFER_MIN_SIZE, 0, this, read_packet, nullptr, seek_packet);
|
||||
|
||||
if(!m_aviocontext)
|
||||
{
|
||||
@ -212,7 +277,14 @@ FFMPEGReader::FFMPEGReader(std::shared_ptr<Buffer> buffer) :
|
||||
|
||||
FFMPEGReader::~FFMPEGReader()
|
||||
{
|
||||
if(m_frame)
|
||||
av_frame_free(&m_frame);
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
avcodec_close(m_codecCtx);
|
||||
#else
|
||||
if(m_codecCtx)
|
||||
avcodec_free_context(&m_codecCtx);
|
||||
#endif
|
||||
avformat_close_input(&m_formatCtx);
|
||||
}
|
||||
|
||||
@ -312,7 +384,7 @@ void FFMPEGReader::seek(int position)
|
||||
}
|
||||
}
|
||||
}
|
||||
av_free_packet(&packet);
|
||||
av_packet_unref(&packet);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -343,7 +415,7 @@ Specs FFMPEGReader::getSpecs() const
|
||||
void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
// read packages and decode them
|
||||
AVPacket packet;
|
||||
AVPacket packet = {};
|
||||
int data_size = 0;
|
||||
int pkgbuf_pos;
|
||||
int left = length;
|
||||
@ -359,7 +431,7 @@ void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
data_size = std::min(pkgbuf_pos, left * sample_size);
|
||||
m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
|
||||
buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
|
||||
left -= data_size/sample_size;
|
||||
left -= data_size / sample_size;
|
||||
}
|
||||
|
||||
// for each frame read as long as there isn't enough data already
|
||||
@ -375,9 +447,9 @@ void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
data_size = std::min(pkgbuf_pos, left * sample_size);
|
||||
m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format));
|
||||
buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
|
||||
left -= data_size/sample_size;
|
||||
left -= data_size / sample_size;
|
||||
}
|
||||
av_free_packet(&packet);
|
||||
av_packet_unref(&packet);
|
||||
}
|
||||
// read more data than necessary?
|
||||
if(pkgbuf_pos > data_size)
|
||||
|
@ -79,6 +79,11 @@ private:
|
||||
*/
|
||||
AVCodecContext* m_codecCtx;
|
||||
|
||||
/**
|
||||
* The AVFrame structure for using ffmpeg.
|
||||
*/
|
||||
AVFrame* m_frame;
|
||||
|
||||
/**
|
||||
* The AVIOContext to read the data from.
|
||||
*/
|
||||
|
218
extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp
vendored
218
extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp
vendored
@ -27,6 +27,10 @@ extern "C" {
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 58
|
||||
#define FFMPEG_OLD_CODE
|
||||
#endif
|
||||
|
||||
void FFMPEGWriter::encode()
|
||||
{
|
||||
sample_t* data = m_input_buffer.getBuffer();
|
||||
@ -58,82 +62,106 @@ void FFMPEGWriter::encode()
|
||||
if(m_input_size)
|
||||
m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(data), m_input_samples * m_specs.channels);
|
||||
|
||||
AVPacket packet;
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
m_packet->data = nullptr;
|
||||
m_packet->size = 0;
|
||||
|
||||
packet.data = nullptr;
|
||||
packet.size = 0;
|
||||
av_init_packet(m_packet);
|
||||
|
||||
av_init_packet(&packet);
|
||||
|
||||
AVFrame* frame = av_frame_alloc();
|
||||
av_frame_unref(frame);
|
||||
av_frame_unref(m_frame);
|
||||
int got_packet;
|
||||
#endif
|
||||
|
||||
frame->nb_samples = m_input_samples;
|
||||
frame->format = m_codecCtx->sample_fmt;
|
||||
frame->channel_layout = m_codecCtx->channel_layout;
|
||||
m_frame->nb_samples = m_input_samples;
|
||||
m_frame->format = m_codecCtx->sample_fmt;
|
||||
m_frame->channel_layout = m_codecCtx->channel_layout;
|
||||
|
||||
if(avcodec_fill_audio_frame(frame, m_specs.channels, m_codecCtx->sample_fmt, reinterpret_cast<data_t*>(data), m_input_buffer.getSize(), 0) < 0)
|
||||
if(avcodec_fill_audio_frame(m_frame, m_specs.channels, m_codecCtx->sample_fmt, reinterpret_cast<data_t*>(data), m_input_buffer.getSize(), 0) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be written, filling the audio frame failed with ffmpeg.");
|
||||
|
||||
AVRational sample_time = { 1, static_cast<int>(m_specs.rate) };
|
||||
frame->pts = av_rescale_q(m_position - m_input_samples, m_codecCtx->time_base, sample_time);
|
||||
m_frame->pts = av_rescale_q(m_position - m_input_samples, m_codecCtx->time_base, sample_time);
|
||||
|
||||
if(avcodec_encode_audio2(m_codecCtx, &packet, frame, &got_packet))
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
if(avcodec_encode_audio2(m_codecCtx, m_packet, m_frame, &got_packet))
|
||||
{
|
||||
av_frame_free(&frame);
|
||||
AUD_THROW(FileException, "File couldn't be written, audio encoding failed with ffmpeg.");
|
||||
}
|
||||
|
||||
if(got_packet)
|
||||
{
|
||||
packet.flags |= AV_PKT_FLAG_KEY;
|
||||
packet.stream_index = m_stream->index;
|
||||
if(av_write_frame(m_formatCtx, &packet) < 0)
|
||||
m_packet->flags |= AV_PKT_FLAG_KEY;
|
||||
m_packet->stream_index = m_stream->index;
|
||||
if(av_write_frame(m_formatCtx, m_packet) < 0)
|
||||
{
|
||||
av_free_packet(&packet);
|
||||
av_frame_free(&frame);
|
||||
av_free_packet(m_packet);
|
||||
AUD_THROW(FileException, "Frame couldn't be writen to the file with ffmpeg.");
|
||||
}
|
||||
av_free_packet(&packet);
|
||||
av_free_packet(m_packet);
|
||||
}
|
||||
#else
|
||||
if(avcodec_send_frame(m_codecCtx, m_frame) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be written, audio encoding failed with ffmpeg.");
|
||||
|
||||
av_frame_free(&frame);
|
||||
while(avcodec_receive_packet(m_codecCtx, m_packet) == 0)
|
||||
{
|
||||
m_packet->stream_index = m_stream->index;
|
||||
|
||||
if(av_write_frame(m_formatCtx, m_packet) < 0)
|
||||
AUD_THROW(FileException, "Frame couldn't be writen to the file with ffmpeg.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FFMPEGWriter::close()
|
||||
{
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
int got_packet = true;
|
||||
|
||||
while(got_packet)
|
||||
{
|
||||
AVPacket packet;
|
||||
m_packet->data = nullptr;
|
||||
m_packet->size = 0;
|
||||
|
||||
packet.data = nullptr;
|
||||
packet.size = 0;
|
||||
av_init_packet(m_packet);
|
||||
|
||||
av_init_packet(&packet);
|
||||
|
||||
if(avcodec_encode_audio2(m_codecCtx, &packet, nullptr, &got_packet))
|
||||
if(avcodec_encode_audio2(m_codecCtx, m_packet, nullptr, &got_packet))
|
||||
AUD_THROW(FileException, "File end couldn't be written, audio encoding failed with ffmpeg.");
|
||||
|
||||
if(got_packet)
|
||||
{
|
||||
packet.flags |= AV_PKT_FLAG_KEY;
|
||||
packet.stream_index = m_stream->index;
|
||||
if(av_write_frame(m_formatCtx, &packet))
|
||||
m_packet->flags |= AV_PKT_FLAG_KEY;
|
||||
m_packet->stream_index = m_stream->index;
|
||||
if(av_write_frame(m_formatCtx, m_packet))
|
||||
{
|
||||
av_free_packet(&packet);
|
||||
av_free_packet(m_packet);
|
||||
AUD_THROW(FileException, "Final frames couldn't be writen to the file with ffmpeg.");
|
||||
}
|
||||
av_free_packet(&packet);
|
||||
av_free_packet(m_packet);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(avcodec_send_frame(m_codecCtx, nullptr) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be written, audio encoding failed with ffmpeg.");
|
||||
|
||||
while(avcodec_receive_packet(m_codecCtx, m_packet) == 0)
|
||||
{
|
||||
m_packet->stream_index = m_stream->index;
|
||||
|
||||
if(av_write_frame(m_formatCtx, m_packet) < 0)
|
||||
AUD_THROW(FileException, "Frame couldn't be writen to the file with ffmpeg.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate) :
|
||||
m_position(0),
|
||||
m_specs(specs),
|
||||
m_formatCtx(nullptr),
|
||||
m_codecCtx(nullptr),
|
||||
m_stream(nullptr),
|
||||
m_packet(nullptr),
|
||||
m_frame(nullptr),
|
||||
m_input_samples(0),
|
||||
m_deinterleave(false)
|
||||
{
|
||||
@ -142,75 +170,105 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
|
||||
if(avformat_alloc_output_context2(&m_formatCtx, nullptr, formats[format], filename.c_str()) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be written, format couldn't be found with ffmpeg.");
|
||||
|
||||
m_outputFmt = m_formatCtx->oformat;
|
||||
AVOutputFormat* outputFmt = m_formatCtx->oformat;
|
||||
|
||||
if(!m_outputFmt) {
|
||||
if(!outputFmt) {
|
||||
avformat_free_context(m_formatCtx);
|
||||
AUD_THROW(FileException, "File couldn't be written, output format couldn't be found with ffmpeg.");
|
||||
}
|
||||
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_NONE;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_NONE;
|
||||
|
||||
switch(codec)
|
||||
{
|
||||
case CODEC_AAC:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_AAC;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_AAC;
|
||||
break;
|
||||
case CODEC_AC3:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_AC3;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_AC3;
|
||||
break;
|
||||
case CODEC_FLAC:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_FLAC;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_FLAC;
|
||||
break;
|
||||
case CODEC_MP2:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_MP2;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_MP2;
|
||||
break;
|
||||
case CODEC_MP3:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_MP3;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_MP3;
|
||||
break;
|
||||
case CODEC_OPUS:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_OPUS;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_OPUS;
|
||||
break;
|
||||
case CODEC_PCM:
|
||||
switch(specs.format)
|
||||
{
|
||||
case FORMAT_U8:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_PCM_U8;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_U8;
|
||||
break;
|
||||
case FORMAT_S16:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_PCM_S16LE;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_S16LE;
|
||||
break;
|
||||
case FORMAT_S24:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_PCM_S24LE;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_S24LE;
|
||||
break;
|
||||
case FORMAT_S32:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_PCM_S32LE;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_S32LE;
|
||||
break;
|
||||
case FORMAT_FLOAT32:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_PCM_F32LE;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_F32LE;
|
||||
break;
|
||||
case FORMAT_FLOAT64:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_PCM_F64LE;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_F64LE;
|
||||
break;
|
||||
default:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_NONE;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_NONE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CODEC_VORBIS:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_VORBIS;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_VORBIS;
|
||||
break;
|
||||
default:
|
||||
m_outputFmt->audio_codec = AV_CODEC_ID_NONE;
|
||||
outputFmt->audio_codec = AV_CODEC_ID_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t channel_layout = 0;
|
||||
|
||||
switch(m_specs.channels)
|
||||
{
|
||||
case CHANNELS_MONO:
|
||||
channel_layout = AV_CH_LAYOUT_MONO;
|
||||
break;
|
||||
case CHANNELS_STEREO:
|
||||
channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
break;
|
||||
case CHANNELS_STEREO_LFE:
|
||||
channel_layout = AV_CH_LAYOUT_2POINT1;
|
||||
break;
|
||||
case CHANNELS_SURROUND4:
|
||||
channel_layout = AV_CH_LAYOUT_QUAD;
|
||||
break;
|
||||
case CHANNELS_SURROUND5:
|
||||
channel_layout = AV_CH_LAYOUT_5POINT0_BACK;
|
||||
break;
|
||||
case CHANNELS_SURROUND51:
|
||||
channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
|
||||
break;
|
||||
case CHANNELS_SURROUND61:
|
||||
channel_layout = AV_CH_LAYOUT_6POINT1_BACK;
|
||||
break;
|
||||
case CHANNELS_SURROUND71:
|
||||
channel_layout = AV_CH_LAYOUT_7POINT1;
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(m_outputFmt->audio_codec == AV_CODEC_ID_NONE)
|
||||
if(outputFmt->audio_codec == AV_CODEC_ID_NONE)
|
||||
AUD_THROW(FileException, "File couldn't be written, audio codec not found with ffmpeg.");
|
||||
|
||||
AVCodec* codec = avcodec_find_encoder(m_outputFmt->audio_codec);
|
||||
AVCodec* codec = avcodec_find_encoder(outputFmt->audio_codec);
|
||||
if(!codec)
|
||||
AUD_THROW(FileException, "File couldn't be written, audio encoder couldn't be found with ffmpeg.");
|
||||
|
||||
@ -220,7 +278,14 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
|
||||
|
||||
m_stream->id = m_formatCtx->nb_streams - 1;
|
||||
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
m_codecCtx = m_stream->codec;
|
||||
#else
|
||||
m_codecCtx = avcodec_alloc_context3(codec);
|
||||
#endif
|
||||
|
||||
if(!m_codecCtx)
|
||||
AUD_THROW(FileException, "File couldn't be written, context creation failed with ffmpeg.");
|
||||
|
||||
switch(m_specs.format)
|
||||
{
|
||||
@ -247,7 +312,7 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
|
||||
}
|
||||
|
||||
if(m_formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
m_codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
m_codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
|
||||
bool format_supported = false;
|
||||
|
||||
@ -328,9 +393,13 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
|
||||
|
||||
m_specs.rate = m_codecCtx->sample_rate;
|
||||
|
||||
m_codecCtx->codec_id = m_outputFmt->audio_codec;
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
m_codecCtx->codec_id = outputFmt->audio_codec;
|
||||
#endif
|
||||
|
||||
m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
m_codecCtx->bit_rate = bitrate;
|
||||
m_codecCtx->channel_layout = channel_layout;
|
||||
m_codecCtx->channels = m_specs.channels;
|
||||
m_stream->time_base.num = m_codecCtx->time_base.num = 1;
|
||||
m_stream->time_base.den = m_codecCtx->time_base.den = m_codecCtx->sample_rate;
|
||||
@ -338,6 +407,11 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
|
||||
if(avcodec_open2(m_codecCtx, codec, nullptr) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be written, encoder couldn't be opened with ffmpeg.");
|
||||
|
||||
#ifndef FFMPEG_OLD_CODE
|
||||
if(avcodec_parameters_from_context(m_stream->codecpar, m_codecCtx) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be written, codec parameters couldn't be copied to the context.");
|
||||
#endif
|
||||
|
||||
int samplesize = std::max(int(AUD_SAMPLE_SIZE(m_specs)), AUD_DEVICE_SAMPLE_SIZE(m_specs));
|
||||
|
||||
if((m_input_size = m_codecCtx->frame_size))
|
||||
@ -346,13 +420,26 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
|
||||
if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_FLAG_WRITE))
|
||||
AUD_THROW(FileException, "File couldn't be written, file opening failed with ffmpeg.");
|
||||
|
||||
avformat_write_header(m_formatCtx, nullptr);
|
||||
if(avformat_write_header(m_formatCtx, nullptr) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be written, writing the header failed.");
|
||||
}
|
||||
catch(Exception&)
|
||||
{
|
||||
#ifndef FFMPEG_OLD_CODE
|
||||
if(m_codecCtx)
|
||||
avcodec_free_context(&m_codecCtx);
|
||||
#endif
|
||||
avformat_free_context(m_formatCtx);
|
||||
throw;
|
||||
}
|
||||
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
m_packet = new AVPacket({});
|
||||
#else
|
||||
m_packet = av_packet_alloc();
|
||||
#endif
|
||||
|
||||
m_frame = av_frame_alloc();
|
||||
}
|
||||
|
||||
FFMPEGWriter::~FFMPEGWriter()
|
||||
@ -365,9 +452,26 @@ FFMPEGWriter::~FFMPEGWriter()
|
||||
|
||||
av_write_trailer(m_formatCtx);
|
||||
|
||||
avcodec_close(m_codecCtx);
|
||||
if(m_frame)
|
||||
av_frame_free(&m_frame);
|
||||
|
||||
avio_close(m_formatCtx->pb);
|
||||
if(m_packet)
|
||||
{
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
delete m_packet;
|
||||
#else
|
||||
av_packet_free(&m_packet);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef FFMPEG_OLD_CODE
|
||||
avcodec_close(m_codecCtx);
|
||||
#else
|
||||
if(m_codecCtx)
|
||||
avcodec_free_context(&m_codecCtx);
|
||||
#endif
|
||||
|
||||
avio_closep(&m_formatCtx->pb);
|
||||
avformat_free_context(m_formatCtx);
|
||||
}
|
||||
|
||||
|
15
extern/audaspace/plugins/ffmpeg/FFMPEGWriter.h
vendored
15
extern/audaspace/plugins/ffmpeg/FFMPEGWriter.h
vendored
@ -65,16 +65,21 @@ private:
|
||||
*/
|
||||
AVCodecContext* m_codecCtx;
|
||||
|
||||
/**
|
||||
* The AVOutputFormat structure for using ffmpeg.
|
||||
*/
|
||||
AVOutputFormat* m_outputFmt;
|
||||
|
||||
/**
|
||||
* The AVStream structure for using ffmpeg.
|
||||
*/
|
||||
AVStream* m_stream;
|
||||
|
||||
/**
|
||||
* The AVPacket structure for using ffmpeg.
|
||||
*/
|
||||
AVPacket* m_packet;
|
||||
|
||||
/**
|
||||
* The AVFrame structure for using ffmpeg.
|
||||
*/
|
||||
AVFrame* m_frame;
|
||||
|
||||
/**
|
||||
* The input buffer for the format converted data before encoding.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user