This file is indexed.

/usr/include/thunderbird/WebMReader.h is in thunderbird-dev 1:24.4.0+build1-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if !defined(WebMReader_h_)
#define WebMReader_h_

#include "mozilla/StandardInteger.h"

#include "nsDeque.h"
#include "MediaDecoderReader.h"
#include "nsAutoRef.h"
#include "nestegg/nestegg.h"

#define VPX_DONT_DEFINE_STDINT_TYPES
#include "vpx/vpx_codec.h"

#ifdef MOZ_TREMOR
#include "tremor/ivorbiscodec.h"
#else
#include "vorbis/codec.h"
#endif

#ifdef MOZ_DASH
#include "DASHRepReader.h"
#endif

namespace mozilla {

class WebMBufferedState;

// Holds a nestegg_packet, and its file offset. This is needed so we
// know the offset in the file we've played up to, in order to calculate
// whether it's likely we can play through to the end without needing
// to stop to buffer, given the current download rate.
class NesteggPacketHolder {
public:
  NesteggPacketHolder(nestegg_packet* aPacket, int64_t aOffset)
    : mPacket(aPacket), mOffset(aOffset)
  {
    MOZ_COUNT_CTOR(NesteggPacketHolder);
  }
  ~NesteggPacketHolder() {
    MOZ_COUNT_DTOR(NesteggPacketHolder);
    nestegg_free_packet(mPacket);
  }
  nestegg_packet* mPacket;
  // Offset in bytes. This is the offset of the end of the Block
  // which contains the packet.
  int64_t mOffset;
private:
  // Copy constructor and assignment operator not implemented. Don't use them!
  NesteggPacketHolder(const NesteggPacketHolder &aOther);
  NesteggPacketHolder& operator= (NesteggPacketHolder const& aOther);
};

// Thread and type safe wrapper around nsDeque.
class PacketQueueDeallocator : public nsDequeFunctor {
  virtual void* operator() (void* anObject) {
    delete static_cast<NesteggPacketHolder*>(anObject);
    return nullptr;
  }
};

// Typesafe queue for holding nestegg packets. It has
// ownership of the items in the queue and will free them
// when destroyed.
class WebMPacketQueue : private nsDeque {
 public:
   WebMPacketQueue()
     : nsDeque(new PacketQueueDeallocator())
   {}
  
  ~WebMPacketQueue() {
    Reset();
  }

  inline int32_t GetSize() { 
    return nsDeque::GetSize();
  }
  
  inline void Push(NesteggPacketHolder* aItem) {
    NS_ASSERTION(aItem, "NULL pushed to WebMPacketQueue");
    nsDeque::Push(aItem);
  }
  
  inline void PushFront(NesteggPacketHolder* aItem) {
    NS_ASSERTION(aItem, "NULL pushed to WebMPacketQueue");
    nsDeque::PushFront(aItem);
  }

  inline NesteggPacketHolder* PopFront() {
    return static_cast<NesteggPacketHolder*>(nsDeque::PopFront());
  }
  
  void Reset() {
    while (GetSize() > 0) {
      delete PopFront();
    }
  }
};

#ifdef MOZ_DASH
class WebMReader : public DASHRepReader
#else
class WebMReader : public MediaDecoderReader
#endif
{
public:
  WebMReader(AbstractMediaDecoder* aDecoder);
  ~WebMReader();

  virtual nsresult Init(MediaDecoderReader* aCloneDonor);
  virtual nsresult ResetDecode();
  virtual bool DecodeAudioData();

  // If the Theora granulepos has not been captured, it may read several packets
  // until one with a granulepos has been captured, to ensure that all packets
  // read have valid time info.  
  virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
                                  int64_t aTimeThreshold);

  virtual bool HasAudio()
  {
    NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    return mHasAudio;
  }

  virtual bool HasVideo()
  {
    NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
    return mHasVideo;
  }

  virtual nsresult ReadMetadata(VideoInfo* aInfo,
                                MetadataTags** aTags);
  virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
  virtual nsresult GetBuffered(TimeRanges* aBuffered, int64_t aStartTime);
  virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);

#ifdef MOZ_DASH
  virtual void SetMainReader(DASHReader *aMainReader) MOZ_OVERRIDE {
    NS_ASSERTION(aMainReader, "aMainReader is null.");
    mMainReader = aMainReader;
  }

  // Called by |DASHReader| on the decode thread so that this reader will
  // start reading at the appropriate subsegment/cluster. If this is not the
  // current reader and a switch was previously requested, then it will seek to
  // starting offset of the subsegment at which it is supposed to switch.
  // Called on the decode thread, enters the decode monitor.
  void PrepareToDecode() MOZ_OVERRIDE;

  // Returns a reference to the audio/video queue of the main reader.
  // Allows for a single audio/video queue to be shared among multiple
  // |WebMReader|s.
  MediaQueue<AudioData>& AudioQueue() MOZ_OVERRIDE {
    if (mMainReader) {
      return mMainReader->AudioQueue();
    } else {
      return MediaDecoderReader::AudioQueue();
    }
  }

  MediaQueue<VideoData>& VideoQueue() MOZ_OVERRIDE {
    if (mMainReader) {
      return mMainReader->VideoQueue();
    } else {
      return MediaDecoderReader::VideoQueue();
    }
  }

  // Sets byte range for initialization (EBML); used by DASH.
  void SetInitByteRange(MediaByteRange &aByteRange) MOZ_OVERRIDE {
    mInitByteRange = aByteRange;
  }

  // Sets byte range for cue points, i.e. cluster offsets; used by DASH.
  void SetIndexByteRange(MediaByteRange &aByteRange) MOZ_OVERRIDE {
    mCuesByteRange = aByteRange;
  }

  // Returns the index of the subsegment which contains the seek time.
  int64_t GetSubsegmentForSeekTime(int64_t aSeekToTime) MOZ_OVERRIDE;

  // Returns list of ranges for cluster start and end offsets.
  nsresult GetSubsegmentByteRanges(nsTArray<MediaByteRange>& aByteRanges)
                                                                  MOZ_OVERRIDE;

  // Called by |DASHReader|::|PossiblySwitchVideoReaders| to check if this
  // reader has reached a switch access point and it's ok to switch readers.
  // Called on the decode thread.
  bool HasReachedSubsegment(uint32_t aSubsegmentIndex) MOZ_OVERRIDE;

  // Requests that this reader seek to the specified subsegment. Seek will
  // happen when |PrepareDecodeVideoFrame| is called on the decode
  // thread.
  // Called on the main thread or decoder thread. Decode monitor must be held.
  void RequestSeekToSubsegment(uint32_t aIdx) MOZ_OVERRIDE;

  // Requests that this reader switch to |aNextReader| at the start of the
  // specified subsegment. This is the reader to switch FROM.
  // Called on the main thread or decoder thread. Decode monitor must be held.
  void RequestSwitchAtSubsegment(int32_t aSubsegmentIdx,
                                 MediaDecoderReader* aNextReader) MOZ_OVERRIDE;

  // Seeks to the beginning of the specified cluster. Called on the decode
  // thread.
  void SeekToCluster(uint32_t aIdx);

  // Returns true if data at the end of the final subsegment has been cached.
  bool IsDataCachedAtEndOfSubsegments() MOZ_OVERRIDE;
#endif

protected:
  // Value passed to NextPacket to determine if we are reading a video or an
  // audio packet.
  enum TrackType {
    VIDEO = 0,
    AUDIO = 1
  };

  // Read a packet from the nestegg file. Returns NULL if all packets for
  // the particular track have been read. Pass VIDEO or AUDIO to indicate the
  // type of the packet we want to read.
#ifdef MOZ_DASH
  nsReturnRef<NesteggPacketHolder> NextPacketInternal(TrackType aTrackType);

  // Read a packet from the nestegg file. Returns NULL if all packets for
  // the particular track have been read. Pass VIDEO or AUDIO to indicate the
  // type of the packet we want to read. If the reader reaches a switch access
  // point, this function will get a packet from |mNextReader|.
#endif
  nsReturnRef<NesteggPacketHolder> NextPacket(TrackType aTrackType);

  // Pushes a packet to the front of the video packet queue.
  virtual void PushVideoPacket(NesteggPacketHolder* aItem);

  // Returns an initialized ogg packet with data obtained from the WebM container.
  ogg_packet InitOggPacket(unsigned char* aData,
                           size_t aLength,
                           bool aBOS,
                           bool aEOS,
                           int64_t aGranulepos);

  // Decode a nestegg packet of audio data. Push the audio data on the
  // audio queue. Returns true when there's more audio to decode,
  // false if the audio is finished, end of file has been reached,
  // or an un-recoverable read error has occured. The reader's monitor
  // must be held during this call. This function will free the packet
  // so the caller must not use the packet after calling.
  bool DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset);

  // Release context and set to null. Called when an error occurs during
  // reading metadata or destruction of the reader itself.
  void Cleanup();

private:
  // libnestegg context for webm container. Access on state machine thread
  // or decoder thread only.
  nestegg* mContext;

  // VP8 decoder state
  vpx_codec_ctx_t mVP8;

  // Vorbis decoder state
  vorbis_info mVorbisInfo;
  vorbis_comment mVorbisComment;
  vorbis_dsp_state mVorbisDsp;
  vorbis_block mVorbisBlock;
  uint32_t mPacketCount;
  uint32_t mChannels;

  // Queue of video and audio packets that have been read but not decoded. These
  // must only be accessed from the state machine thread.
  WebMPacketQueue mVideoPackets;
  WebMPacketQueue mAudioPackets;

  // Index of video and audio track to play
  uint32_t mVideoTrack;
  uint32_t mAudioTrack;

  // Time in microseconds of the start of the first audio frame we've decoded.
  int64_t mAudioStartUsec;

  // Number of audio frames we've decoded since decoding began at mAudioStartMs.
  uint64_t mAudioFrames;

  // Parser state and computed offset-time mappings.  Shared by multiple
  // readers when decoder has been cloned.  Main thread only.
  nsRefPtr<WebMBufferedState> mBufferedState;

  // Size of the frame initially present in the stream. The picture region
  // is defined as a ratio relative to this.
  nsIntSize mInitialFrame;

  // Picture region, as relative to the initial frame size.
  nsIntRect mPicture;

  // Booleans to indicate if we have audio and/or video data
  bool mHasVideo;
  bool mHasAudio;

#ifdef MOZ_DASH
  // Byte range for initialisation data; e.g. specified in DASH manifest.
  MediaByteRange mInitByteRange;

  // Byte range for cues; e.g. specified in DASH manifest.
  MediaByteRange mCuesByteRange;

  // Byte ranges for clusters; set internally, derived from cues.
  nsTArray<TimestampedMediaByteRange> mClusterByteRanges;

  // Pointer to the main |DASHReader|. Set in the constructor.
  DASHReader* mMainReader;

  // Index of the cluster to switch to. Monitor must be entered for write
  // access on all threads, read access off the decode thread.
  int32_t mSwitchingCluster;

  // Pointer to the next reader. Used in |NextPacket| and |PushVideoPacket| at
  // switch access points. Monitor must be entered for write access on all
  // threads, read access off the decode thread.
  nsRefPtr<WebMReader> mNextReader;

  // Index of the cluster to seek to for a DASH stream request. Monitor must be
  // entered for write access on all threads, read access off the decode
  // thread.
  int32_t mSeekToCluster;

  // Current end offset of the last packet read in |NextPacket|. Used to check
  // if the reader reached the switch access point. Accessed on the decode
  // thread only.
  int64_t mCurrentOffset;

  // Index of next cluster to be read. Used to determine the starting offset of
  // the next cluster. Accessed on the decode thread only.
  uint32_t mNextCluster;

  // Set in |NextPacket| if we read a packet from the next reader. If true in
  // |PushVideoPacket|, we will push the packet onto the next reader's
  // video packet queue (not video data queue!). Accessed on decode thread
  // only.
  bool mPushVideoPacketToNextReader;

  // Indicates if the reader has reached a switch access point.  Set in
  // |NextPacket| and read in |HasReachedSubsegment|. Accessed on
  // decode thread only.
  bool mReachedSwitchAccessPoint;
#endif
};

} // namespace mozilla

#endif