content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "MediaTaskQueue.h"
michael@0 8 #include "FFmpegRuntimeLinker.h"
michael@0 9
michael@0 10 #include "FFmpegAACDecoder.h"
michael@0 11
michael@0 12 #define MAX_CHANNELS 16
michael@0 13
michael@0 14 typedef mp4_demuxer::MP4Sample MP4Sample;
michael@0 15
michael@0 16 namespace mozilla
michael@0 17 {
michael@0 18
michael@0 19 FFmpegAACDecoder::FFmpegAACDecoder(
michael@0 20 MediaTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
michael@0 21 const mp4_demuxer::AudioDecoderConfig &aConfig)
michael@0 22 : FFmpegDataDecoder(aTaskQueue, AV_CODEC_ID_AAC)
michael@0 23 , mCallback(aCallback)
michael@0 24 , mConfig(aConfig)
michael@0 25 {
michael@0 26 MOZ_COUNT_CTOR(FFmpegAACDecoder);
michael@0 27 }
michael@0 28
michael@0 29 nsresult
michael@0 30 FFmpegAACDecoder::Init()
michael@0 31 {
michael@0 32 nsresult rv = FFmpegDataDecoder::Init();
michael@0 33 NS_ENSURE_SUCCESS(rv, rv);
michael@0 34
michael@0 35 return NS_OK;
michael@0 36 }
michael@0 37
michael@0 38 static AudioDataValue*
michael@0 39 CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumSamples)
michael@0 40 {
michael@0 41 // These are the only two valid AAC packet sizes.
michael@0 42 NS_ASSERTION(aNumSamples == 960 || aNumSamples == 1024,
michael@0 43 "Should have exactly one AAC audio packet.");
michael@0 44 MOZ_ASSERT(aNumChannels <= MAX_CHANNELS);
michael@0 45
michael@0 46 nsAutoArrayPtr<AudioDataValue> audio(
michael@0 47 new AudioDataValue[aNumChannels * aNumSamples]);
michael@0 48
michael@0 49 AudioDataValue** data = reinterpret_cast<AudioDataValue**>(aFrame->data);
michael@0 50
michael@0 51 if (aFrame->format == AV_SAMPLE_FMT_FLT) {
michael@0 52 // Audio data already packed. No need to do anything other than copy it
michael@0 53 // into a buffer we own.
michael@0 54 memcpy(audio, data[0], aNumChannels * aNumSamples * sizeof(AudioDataValue));
michael@0 55 } else if (aFrame->format == AV_SAMPLE_FMT_FLTP) {
michael@0 56 // Planar audio data. Pack it into something we can understand.
michael@0 57 for (uint32_t channel = 0; channel < aNumChannels; channel++) {
michael@0 58 for (uint32_t sample = 0; sample < aNumSamples; sample++) {
michael@0 59 audio[sample * aNumChannels + channel] = data[channel][sample];
michael@0 60 }
michael@0 61 }
michael@0 62 }
michael@0 63
michael@0 64 return audio.forget();
michael@0 65 }
michael@0 66
michael@0 67 void
michael@0 68 FFmpegAACDecoder::DecodePacket(MP4Sample* aSample)
michael@0 69 {
michael@0 70 nsAutoPtr<AVFrame> frame(avcodec_alloc_frame());
michael@0 71 avcodec_get_frame_defaults(frame);
michael@0 72
michael@0 73 AVPacket packet;
michael@0 74 av_init_packet(&packet);
michael@0 75
michael@0 76 packet.data = &(*aSample->data)[0];
michael@0 77 packet.size = aSample->data->size();
michael@0 78 packet.pos = aSample->byte_offset;
michael@0 79 packet.dts = aSample->decode_timestamp;
michael@0 80
michael@0 81 int decoded;
michael@0 82 int bytesConsumed =
michael@0 83 avcodec_decode_audio4(&mCodecContext, frame.get(), &decoded, &packet);
michael@0 84
michael@0 85 if (bytesConsumed < 0 || !decoded) {
michael@0 86 NS_WARNING("FFmpeg audio decoder error.");
michael@0 87 mCallback->Error();
michael@0 88 return;
michael@0 89 }
michael@0 90
michael@0 91 NS_ASSERTION(bytesConsumed == (int)aSample->data->size(),
michael@0 92 "Only one audio packet should be received at a time.");
michael@0 93
michael@0 94 uint32_t numChannels = mCodecContext.channels;
michael@0 95
michael@0 96 nsAutoArrayPtr<AudioDataValue> audio(
michael@0 97 CopyAndPackAudio(frame.get(), numChannels, frame->nb_samples));
michael@0 98
michael@0 99 nsAutoPtr<AudioData> data(new AudioData(packet.pos, aSample->decode_timestamp,
michael@0 100 aSample->duration, frame->nb_samples,
michael@0 101 audio.forget(), numChannels));
michael@0 102
michael@0 103 mCallback->Output(data.forget());
michael@0 104
michael@0 105 if (mTaskQueue->IsEmpty()) {
michael@0 106 mCallback->InputExhausted();
michael@0 107 }
michael@0 108 }
michael@0 109
michael@0 110 nsresult
michael@0 111 FFmpegAACDecoder::Input(MP4Sample* aSample)
michael@0 112 {
michael@0 113 mTaskQueue->Dispatch(NS_NewRunnableMethodWithArg<nsAutoPtr<MP4Sample> >(
michael@0 114 this, &FFmpegAACDecoder::DecodePacket, nsAutoPtr<MP4Sample>(aSample)));
michael@0 115
michael@0 116 return NS_OK;
michael@0 117 }
michael@0 118
michael@0 119 nsresult
michael@0 120 FFmpegAACDecoder::Drain()
michael@0 121 {
michael@0 122 // AAC is never delayed; nothing to do here.
michael@0 123 return NS_OK;
michael@0 124 }
michael@0 125
michael@0 126 FFmpegAACDecoder::~FFmpegAACDecoder() {
michael@0 127 MOZ_COUNT_DTOR(FFmpegAACDecoder);
michael@0 128 }
michael@0 129
michael@0 130 } // namespace mozilla

mercurial