content/media/webm/WebMReader.h

branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
equal deleted inserted replaced
-1:000000000000 0:30af3ca883cf
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/. */
6 #if !defined(WebMReader_h_)
7 #define WebMReader_h_
8
9 #include <stdint.h>
10
11 #include "nsDeque.h"
12 #include "MediaDecoderReader.h"
13 #include "nsAutoRef.h"
14 #include "nestegg/nestegg.h"
15
16 #define VPX_DONT_DEFINE_STDINT_TYPES
17 #include "vpx/vpx_codec.h"
18
19 #ifdef MOZ_TREMOR
20 #include "tremor/ivorbiscodec.h"
21 #else
22 #include "vorbis/codec.h"
23 #endif
24
25 #ifdef MOZ_OPUS
26 #include "OpusParser.h"
27 #endif
28
29 namespace mozilla {
30
31 class WebMBufferedState;
32
33 // Holds a nestegg_packet, and its file offset. This is needed so we
34 // know the offset in the file we've played up to, in order to calculate
35 // whether it's likely we can play through to the end without needing
36 // to stop to buffer, given the current download rate.
37 class NesteggPacketHolder {
38 public:
39 NesteggPacketHolder(nestegg_packet* aPacket, int64_t aOffset)
40 : mPacket(aPacket), mOffset(aOffset)
41 {
42 MOZ_COUNT_CTOR(NesteggPacketHolder);
43 }
44 ~NesteggPacketHolder() {
45 MOZ_COUNT_DTOR(NesteggPacketHolder);
46 nestegg_free_packet(mPacket);
47 }
48 nestegg_packet* mPacket;
49 // Offset in bytes. This is the offset of the end of the Block
50 // which contains the packet.
51 int64_t mOffset;
52 private:
53 // Copy constructor and assignment operator not implemented. Don't use them!
54 NesteggPacketHolder(const NesteggPacketHolder &aOther);
55 NesteggPacketHolder& operator= (NesteggPacketHolder const& aOther);
56 };
57
58 // Thread and type safe wrapper around nsDeque.
59 class PacketQueueDeallocator : public nsDequeFunctor {
60 virtual void* operator() (void* anObject) {
61 delete static_cast<NesteggPacketHolder*>(anObject);
62 return nullptr;
63 }
64 };
65
66 // Typesafe queue for holding nestegg packets. It has
67 // ownership of the items in the queue and will free them
68 // when destroyed.
69 class WebMPacketQueue : private nsDeque {
70 public:
71 WebMPacketQueue()
72 : nsDeque(new PacketQueueDeallocator())
73 {}
74
75 ~WebMPacketQueue() {
76 Reset();
77 }
78
79 inline int32_t GetSize() {
80 return nsDeque::GetSize();
81 }
82
83 inline void Push(NesteggPacketHolder* aItem) {
84 NS_ASSERTION(aItem, "NULL pushed to WebMPacketQueue");
85 nsDeque::Push(aItem);
86 }
87
88 inline void PushFront(NesteggPacketHolder* aItem) {
89 NS_ASSERTION(aItem, "NULL pushed to WebMPacketQueue");
90 nsDeque::PushFront(aItem);
91 }
92
93 inline NesteggPacketHolder* PopFront() {
94 return static_cast<NesteggPacketHolder*>(nsDeque::PopFront());
95 }
96
97 void Reset() {
98 while (GetSize() > 0) {
99 delete PopFront();
100 }
101 }
102 };
103
104 class WebMReader : public MediaDecoderReader
105 {
106 public:
107 WebMReader(AbstractMediaDecoder* aDecoder);
108 ~WebMReader();
109
110 virtual nsresult Init(MediaDecoderReader* aCloneDonor);
111 virtual nsresult ResetDecode();
112 virtual bool DecodeAudioData();
113
114 // If the Theora granulepos has not been captured, it may read several packets
115 // until one with a granulepos has been captured, to ensure that all packets
116 // read have valid time info.
117 virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
118 int64_t aTimeThreshold);
119
120 virtual bool HasAudio()
121 {
122 NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
123 return mHasAudio;
124 }
125
126 virtual bool HasVideo()
127 {
128 NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
129 return mHasVideo;
130 }
131
132 virtual nsresult ReadMetadata(MediaInfo* aInfo,
133 MetadataTags** aTags);
134 virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
135 virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);
136 virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
137
138 protected:
139 // Value passed to NextPacket to determine if we are reading a video or an
140 // audio packet.
141 enum TrackType {
142 VIDEO = 0,
143 AUDIO = 1
144 };
145
146 // Read a packet from the nestegg file. Returns nullptr if all packets for
147 // the particular track have been read. Pass VIDEO or AUDIO to indicate the
148 // type of the packet we want to read.
149 nsReturnRef<NesteggPacketHolder> NextPacket(TrackType aTrackType);
150
151 // Pushes a packet to the front of the video packet queue.
152 virtual void PushVideoPacket(NesteggPacketHolder* aItem);
153
154 // Returns an initialized ogg packet with data obtained from the WebM container.
155 ogg_packet InitOggPacket(unsigned char* aData,
156 size_t aLength,
157 bool aBOS,
158 bool aEOS,
159 int64_t aGranulepos);
160
161 #ifdef MOZ_OPUS
162 // Setup opus decoder
163 bool InitOpusDecoder();
164 #endif
165
166 // Decode a nestegg packet of audio data. Push the audio data on the
167 // audio queue. Returns true when there's more audio to decode,
168 // false if the audio is finished, end of file has been reached,
169 // or an un-recoverable read error has occured. The reader's monitor
170 // must be held during this call. The caller is responsible for freeing
171 // aPacket.
172 bool DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset);
173
174 // Release context and set to null. Called when an error occurs during
175 // reading metadata or destruction of the reader itself.
176 void Cleanup();
177
178 private:
179 // libnestegg context for webm container. Access on state machine thread
180 // or decoder thread only.
181 nestegg* mContext;
182
183 // VP8 decoder state
184 vpx_codec_ctx_t mVPX;
185
186 // Vorbis decoder state
187 vorbis_info mVorbisInfo;
188 vorbis_comment mVorbisComment;
189 vorbis_dsp_state mVorbisDsp;
190 vorbis_block mVorbisBlock;
191 uint32_t mPacketCount;
192 uint32_t mChannels;
193
194
195 #ifdef MOZ_OPUS
196 // Opus decoder state
197 nsAutoPtr<OpusParser> mOpusParser;
198 OpusMSDecoder *mOpusDecoder;
199 int mSkip; // Number of samples left to trim before playback.
200 uint64_t mSeekPreroll; // Number of nanoseconds that must be discarded after seeking.
201 #endif
202
203 // Queue of video and audio packets that have been read but not decoded. These
204 // must only be accessed from the state machine thread.
205 WebMPacketQueue mVideoPackets;
206 WebMPacketQueue mAudioPackets;
207
208 // Index of video and audio track to play
209 uint32_t mVideoTrack;
210 uint32_t mAudioTrack;
211
212 // Time in microseconds of the start of the first audio frame we've decoded.
213 int64_t mAudioStartUsec;
214
215 // Number of audio frames we've decoded since decoding began at mAudioStartMs.
216 uint64_t mAudioFrames;
217
218 // Number of microseconds that must be discarded from the start of the Stream.
219 uint64_t mCodecDelay;
220
221 // Parser state and computed offset-time mappings. Shared by multiple
222 // readers when decoder has been cloned. Main thread only.
223 nsRefPtr<WebMBufferedState> mBufferedState;
224
225 // Size of the frame initially present in the stream. The picture region
226 // is defined as a ratio relative to this.
227 nsIntSize mInitialFrame;
228
229 // Picture region, as relative to the initial frame size.
230 nsIntRect mPicture;
231
232 // Codec ID of audio track
233 int mAudioCodec;
234 // Codec ID of video track
235 int mVideoCodec;
236
237 // Booleans to indicate if we have audio and/or video data
238 bool mHasVideo;
239 bool mHasAudio;
240 };
241
242 } // namespace mozilla
243
244 #endif

mercurial