content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial