Tue, 06 Jan 2015 21:39:09 +0100
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