整理代码
This commit is contained in:
commit
c7b4e178ec
364 changed files with 59691 additions and 0 deletions
179
video/ffmpeg/AudioEncoder.cpp
Normal file
179
video/ffmpeg/AudioEncoder.cpp
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* INCLUDE
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "AudioEncoder.h"
|
||||
#include "Util.h"
|
||||
#include "Logger.h"
|
||||
#include "../core/System.h"
|
||||
|
||||
namespace Video
|
||||
{
|
||||
namespace FFmpeg
|
||||
{
|
||||
/*
|
||||
*******************************************************************************
|
||||
* CLASS DEFINE
|
||||
*******************************************************************************
|
||||
*/
|
||||
AudioEncoder::AudioEncoder(Core::CodecID codecID)
|
||||
: Core::AudioEncoder(Poco::format("FFmpeg::AudioEncoder(%s)", Core::codecIDToString(codecID)), codecID),
|
||||
_pCodecCtx(nullptr), _pFrame(nullptr), _pPacket(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
AudioEncoder::~AudioEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
void AudioEncoder::initialize()
|
||||
{
|
||||
auto codecID = getCodecID();
|
||||
const AVCodec* pCodec = Util::getEncoder(codecID);
|
||||
if (!pCodec)
|
||||
throw Poco::NotImplementedException(
|
||||
Poco::format("%s: Unsupported codec: %s", name(), Core::codecIDToString(codecID)), -EINVAL);
|
||||
|
||||
_pCodecCtx = avcodec_alloc_context3(pCodec);
|
||||
if (!_pCodecCtx)
|
||||
throw Poco::InvalidAccessException(Poco::format("%s: Could not alloc an encoding context", name()), -EACCES);
|
||||
|
||||
setChannelLayout(Core::ChannelLayout::STEREO);
|
||||
switch (pCodec->id)
|
||||
{
|
||||
case AV_CODEC_ID_PCM_ALAW:
|
||||
case AV_CODEC_ID_PCM_MULAW:
|
||||
setSampleFormat(Core::SampleFormat::S16P);
|
||||
setSampleRate(8000);
|
||||
|
||||
if (Core::channelLayoutChannels(getChannelLayout()) != 1)
|
||||
setChannelLayout(Core::ChannelLayout::MONO);
|
||||
setFrameSize(320);
|
||||
break;
|
||||
|
||||
case AV_CODEC_ID_AAC:
|
||||
setSampleFormat(Core::SampleFormat::FLTP);
|
||||
setFrameSize(1024);
|
||||
break;
|
||||
|
||||
case AV_CODEC_ID_MP3:
|
||||
setSampleFormat(Core::SampleFormat::FLTP);
|
||||
setFrameSize(1152);
|
||||
break;
|
||||
|
||||
case AV_CODEC_ID_OPUS:
|
||||
_pCodecCtx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
|
||||
setSampleFormat(Core::SampleFormat::S16);
|
||||
setFrameSize(960);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Poco::BugcheckException(
|
||||
Poco::format("%s: Unspecified encoder(%s) parameters", name(), Core::codecIDToString(codecID)), -EINVAL);
|
||||
}
|
||||
|
||||
_pCodecCtx->ch_layout = Util::getChannelLayout(getChannelLayout());
|
||||
_pCodecCtx->sample_rate = getSampleRate();
|
||||
_pCodecCtx->bit_rate = getBitrate();
|
||||
_pCodecCtx->sample_fmt = Util::getSampleFormat(getSampleFormat());
|
||||
_pCodecCtx->time_base = (AVRational){1, getSampleRate()};
|
||||
int rc = avcodec_open2(_pCodecCtx, pCodec, nullptr);
|
||||
if (rc < 0)
|
||||
throw Poco::InvalidAccessException(
|
||||
Poco::format("%s: Open %s FAIL: %d(%s)", name(), std::string(pCodec->name), rc, Util::getErrorString(rc)),
|
||||
rc);
|
||||
|
||||
if (_pCodecCtx->frame_size == 0)
|
||||
_pCodecCtx->frame_size = getFrameSize();
|
||||
|
||||
_pFrame = av_frame_alloc();
|
||||
_pFrame->format = _pCodecCtx->sample_fmt;
|
||||
_pFrame->sample_rate = _pCodecCtx->sample_rate;
|
||||
_pFrame->nb_samples = _pCodecCtx->frame_size;
|
||||
av_channel_layout_copy(&_pFrame->ch_layout, &_pCodecCtx->ch_layout);
|
||||
av_frame_get_buffer(_pFrame, 0);
|
||||
|
||||
if (Core::sampleFormatIsPlanar(getSampleFormat()))
|
||||
{
|
||||
const int c = Core::channelLayoutChannels(getChannelLayout());
|
||||
switch (c)
|
||||
{
|
||||
case 1:
|
||||
_frameConvertor = [](Core::Frame::Ptr from, AVFrame* to) -> void
|
||||
{ memcpy(to->data[0], from->data[0], from->length); };
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_frameConvertor = [](Core::Frame::Ptr from, AVFrame* to) -> void
|
||||
{
|
||||
memcpy(to->data[0], from->data[0], from->length);
|
||||
memcpy(to->data[1], from->data[1], from->length);
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Poco::BugcheckException(Poco::format("%s: Unsupported channle-count: %d", name(), c), -EINVAL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_frameConvertor = [](Core::Frame::Ptr from, AVFrame* to) -> void
|
||||
{ memcpy(to->data[0], from->data[0], from->length); };
|
||||
}
|
||||
}
|
||||
|
||||
void AudioEncoder::deinitialize()
|
||||
{
|
||||
av_frame_free(&_pFrame);
|
||||
|
||||
avcodec_free_context(&_pCodecCtx);
|
||||
}
|
||||
|
||||
Core::Packet::Ptr AudioEncoder::encode()
|
||||
{
|
||||
if (_pPacket == nullptr)
|
||||
_pPacket = av_packet_alloc();
|
||||
|
||||
int rc = avcodec_receive_packet(_pCodecCtx, _pPacket);
|
||||
if (rc > 0)
|
||||
{
|
||||
return new Core::Packet(serialCodeManager().code(), false, &_pPacket);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto pIn = readFrame();
|
||||
ts = pIn->timestamp;
|
||||
rc = av_frame_make_writable(_pFrame);
|
||||
if (rc < 0)
|
||||
throw Poco::InvalidAccessException(
|
||||
Poco::format("%s: Make frame writable failed: %d(%s)", name(), rc, Util::getErrorString(rc)), rc);
|
||||
|
||||
_frameConvertor(pIn, _pFrame);
|
||||
_pFrame->pts = pIn->timestamp;
|
||||
|
||||
int rc = avcodec_send_frame(_pCodecCtx, _pFrame);
|
||||
if (rc < 0)
|
||||
throw Poco::InvalidAccessException(Poco::format("%s: Sending the frame to the encoder failed: %d(%s)",
|
||||
name(), rc, Util::getErrorString(rc)),
|
||||
rc);
|
||||
|
||||
rc = avcodec_receive_packet(_pCodecCtx, _pPacket);
|
||||
if (rc == AVERROR(EAGAIN) || rc == AVERROR_EOF)
|
||||
continue;
|
||||
|
||||
if (rc < 0)
|
||||
throw Poco::InvalidAccessException(
|
||||
Poco::format("%s: Error encoding audio frame: %d(%s)", name(), rc, Util::getErrorString(rc)), rc);
|
||||
|
||||
return new Core::Packet(serialCodeManager().code(), false, &_pPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioEncoder::onConfigChanged(ParameterNames& names)
|
||||
{
|
||||
Core::AudioEncoder::onConfigChanged(names);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue