Video: Support AAC in MP4
Jeffrey Pfau jeffrey@endrift.com
Tue, 28 Oct 2014 23:30:15 -0700
2 files changed,
35 insertions(+),
7 deletions(-)
M
src/platform/ffmpeg/ffmpeg-encoder.c
→
src/platform/ffmpeg/ffmpeg-encoder.c
@@ -2,6 +2,8 @@ #include "ffmpeg-encoder.h"
#include "gba-video.h" +#include <libavcodec/avcodec.h> + #include <libavutil/imgutils.h> #include <libavutil/opt.h>@@ -27,6 +29,8 @@ encoder->containerFormat = 0;
FFmpegEncoderSetAudio(encoder, "flac", 0); FFmpegEncoderSetVideo(encoder, "png", 0); FFmpegEncoderSetContainer(encoder, "matroska"); + encoder->resampleContext = 0; + encoder->absf = 0; encoder->context = 0; }@@ -200,6 +204,14 @@ encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0);
encoder->postaudioBuffer = av_malloc(encoder->postaudioBufferSize); avcodec_fill_audio_frame(encoder->audioFrame, encoder->audio->channels, encoder->audio->sample_fmt, (const uint8_t*) encoder->postaudioBuffer, encoder->postaudioBufferSize, 0); + if (encoder->audio->codec->id == AV_CODEC_ID_AAC && + (strcasecmp(encoder->containerFormat, "mp4") || + strcasecmp(encoder->containerFormat, "m4v") || + strcasecmp(encoder->containerFormat, "mov"))) { + // MP4 container doesn't support the raw ADTS AAC format that the encoder spits out + encoder->absf = av_bitstream_filter_init("aac_adtstoasc"); + } + encoder->videoStream = avformat_new_stream(encoder->context, vcodec); encoder->video = encoder->videoStream->codec; encoder->video->bit_rate = encoder->videoBitrate;@@ -252,6 +264,11 @@ if (encoder->resampleContext) {
avresample_close(encoder->resampleContext); } + if (encoder->absf) { + av_bitstream_filter_close(encoder->absf); + encoder->absf = 0; + } + sws_freeContext(encoder->scaleContext); avformat_free_context(encoder->context);@@ -296,6 +313,17 @@ packet.size = 0;
int gotData; avcodec_encode_audio2(encoder->audio, &packet, encoder->audioFrame, &gotData); if (gotData) { + if (encoder->absf) { + AVPacket tempPacket = packet; + int success = av_bitstream_filter_filter(encoder->absf, encoder->audio, 0, + &tempPacket.data, &tempPacket.size, + packet.data, packet.size, 0); + if (success > 0) { + tempPacket.buf = av_buffer_create(tempPacket.data, tempPacket.size, av_buffer_default_free, 0, 0); + av_free_packet(&packet); + } + packet = tempPacket; + } packet.stream_index = encoder->audioStream->index; av_interleaved_write_frame(encoder->context, &packet); }
M
src/platform/ffmpeg/ffmpeg-encoder.h
→
src/platform/ffmpeg/ffmpeg-encoder.h
@@ -3,12 +3,11 @@ #define FFMPEG_ENCODER
#include "gba-thread.h" -#include <libavcodec/avcodec.h> #include <libavformat/avformat.h> struct FFmpegEncoder { struct GBAAVStream d; - AVFormatContext* context; + struct AVFormatContext* context; unsigned audioBitrate; const char* audioCodec;@@ -18,7 +17,7 @@ const char* videoCodec;
const char* containerFormat; - AVCodecContext* audio; + struct AVCodecContext* audio; enum AVSampleFormat sampleFormat; int sampleRate; uint16_t* audioBuffer;@@ -30,14 +29,15 @@ size_t currentAudioSample;
int64_t currentAudioFrame; int64_t nextAudioPts; struct AVAudioResampleContext* resampleContext; - AVStream* audioStream; + struct AVBitStreamFilterContext* absf; // Needed for AAC in MP4 + struct AVStream* audioStream; - AVCodecContext* video; + struct AVCodecContext* video; enum AVPixelFormat pixFormat; - AVFrame* videoFrame; + struct AVFrame* videoFrame; int64_t currentVideoFrame; struct SwsContext* scaleContext; - AVStream* videoStream; + struct AVStream* videoStream; }; void FFmpegEncoderInit(struct FFmpegEncoder*);