|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
|
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(MediaDecoderReader_h_) |
|
7 #define MediaDecoderReader_h_ |
|
8 |
|
9 #include "AbstractMediaDecoder.h" |
|
10 #include "MediaInfo.h" |
|
11 #include "MediaData.h" |
|
12 #include "MediaQueue.h" |
|
13 #include "AudioCompactor.h" |
|
14 |
|
15 namespace mozilla { |
|
16 |
|
17 namespace dom { |
|
18 class TimeRanges; |
|
19 } |
|
20 |
|
21 // Encapsulates the decoding and reading of media data. Reading can only be |
|
22 // done on the decode thread. Never hold the decoder monitor when |
|
23 // calling into this class. Unless otherwise specified, methods and fields of |
|
24 // this class can only be accessed on the decode thread. |
|
25 class MediaDecoderReader { |
|
26 public: |
|
27 MediaDecoderReader(AbstractMediaDecoder* aDecoder); |
|
28 virtual ~MediaDecoderReader(); |
|
29 |
|
30 // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE |
|
31 // on failure. |
|
32 virtual nsresult Init(MediaDecoderReader* aCloneDonor) = 0; |
|
33 |
|
34 // True if this reader is waiting media resource allocation |
|
35 virtual bool IsWaitingMediaResources() { return false; } |
|
36 // True when this reader need to become dormant state |
|
37 virtual bool IsDormantNeeded() { return false; } |
|
38 // Release media resources they should be released in dormant state |
|
39 virtual void ReleaseMediaResources() {}; |
|
40 // Release the decoder during shutdown |
|
41 virtual void ReleaseDecoder() {}; |
|
42 |
|
43 // Resets all state related to decoding, emptying all buffers etc. |
|
44 virtual nsresult ResetDecode(); |
|
45 |
|
46 // Decodes an unspecified amount of audio data, enqueuing the audio data |
|
47 // in mAudioQueue. Returns true when there's more audio to decode, |
|
48 // false if the audio is finished, end of file has been reached, |
|
49 // or an un-recoverable read error has occured. |
|
50 virtual bool DecodeAudioData() = 0; |
|
51 |
|
52 // Reads and decodes one video frame. Packets with a timestamp less |
|
53 // than aTimeThreshold will be decoded (unless they're not keyframes |
|
54 // and aKeyframeSkip is true), but will not be added to the queue. |
|
55 virtual bool DecodeVideoFrame(bool &aKeyframeSkip, |
|
56 int64_t aTimeThreshold) = 0; |
|
57 |
|
58 virtual bool HasAudio() = 0; |
|
59 virtual bool HasVideo() = 0; |
|
60 |
|
61 // Read header data for all bitstreams in the file. Fills aInfo with |
|
62 // the data required to present the media, and optionally fills *aTags |
|
63 // with tag metadata from the file. |
|
64 // Returns NS_OK on success, or NS_ERROR_FAILURE on failure. |
|
65 virtual nsresult ReadMetadata(MediaInfo* aInfo, |
|
66 MetadataTags** aTags) = 0; |
|
67 |
|
68 // Stores the presentation time of the first frame we'd be able to play if |
|
69 // we started playback at the current position. Returns the first video |
|
70 // frame, if we have video. |
|
71 virtual VideoData* FindStartTime(int64_t& aOutStartTime); |
|
72 |
|
73 // Moves the decode head to aTime microseconds. aStartTime and aEndTime |
|
74 // denote the start and end times of the media in usecs, and aCurrentTime |
|
75 // is the current playback position in microseconds. |
|
76 virtual nsresult Seek(int64_t aTime, |
|
77 int64_t aStartTime, |
|
78 int64_t aEndTime, |
|
79 int64_t aCurrentTime) = 0; |
|
80 |
|
81 // Called to move the reader into idle/active state. When the reader is |
|
82 // created it is assumed to be active (i.e. not idle). When the media |
|
83 // element is paused and we don't need to decode any more data, the state |
|
84 // machine calls SetIdle() to inform the reader that its decoder won't be |
|
85 // needed for a while. When we need to decode data again, the state machine |
|
86 // calls SetActive() to activate the decoder. The reader can use these |
|
87 // notifications to enter/exit a low power state when the decoder isn't |
|
88 // needed, if desired. This is most useful on mobile. |
|
89 virtual void SetIdle() { } |
|
90 virtual void SetActive() { } |
|
91 |
|
92 // Tell the reader that the data decoded are not for direct playback, so it |
|
93 // can accept more files, in particular those which have more channels than |
|
94 // available in the audio output. |
|
95 void SetIgnoreAudioOutputFormat() |
|
96 { |
|
97 mIgnoreAudioOutputFormat = true; |
|
98 } |
|
99 |
|
100 protected: |
|
101 // Queue of audio frames. This queue is threadsafe, and is accessed from |
|
102 // the audio, decoder, state machine, and main threads. |
|
103 MediaQueue<AudioData> mAudioQueue; |
|
104 |
|
105 // Queue of video frames. This queue is threadsafe, and is accessed from |
|
106 // the decoder, state machine, and main threads. |
|
107 MediaQueue<VideoData> mVideoQueue; |
|
108 |
|
109 // An adapter to the audio queue which first copies data to buffers with |
|
110 // minimal allocation slop and then pushes them to the queue. This is |
|
111 // useful for decoders working with formats that give awkward numbers of |
|
112 // frames such as mp3. |
|
113 AudioCompactor mAudioCompactor; |
|
114 |
|
115 public: |
|
116 // Populates aBuffered with the time ranges which are buffered. aStartTime |
|
117 // must be the presentation time of the first frame in the media, e.g. |
|
118 // the media time corresponding to playback time/position 0. This function |
|
119 // is called on the main, decode, and state machine threads. |
|
120 // |
|
121 // This base implementation in MediaDecoderReader estimates the time ranges |
|
122 // buffered by interpolating the cached byte ranges with the duration |
|
123 // of the media. Reader subclasses should override this method if they |
|
124 // can quickly calculate the buffered ranges more accurately. |
|
125 // |
|
126 // The primary advantage of this implementation in the reader base class |
|
127 // is that it's a fast approximation, which does not perform any I/O. |
|
128 // |
|
129 // The OggReader relies on this base implementation not performing I/O, |
|
130 // since in FirefoxOS we can't do I/O on the main thread, where this is |
|
131 // called. |
|
132 virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, |
|
133 int64_t aStartTime); |
|
134 |
|
135 // Returns the number of bytes of memory allocated by structures/frames in |
|
136 // the video queue. |
|
137 size_t SizeOfVideoQueueInBytes() const; |
|
138 |
|
139 // Returns the number of bytes of memory allocated by structures/frames in |
|
140 // the audio queue. |
|
141 size_t SizeOfAudioQueueInBytes() const; |
|
142 |
|
143 // Only used by WebMReader and MediaOmxReader for now, so stub here rather |
|
144 // than in every reader than inherits from MediaDecoderReader. |
|
145 virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) {} |
|
146 |
|
147 virtual MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; } |
|
148 virtual MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; } |
|
149 |
|
150 // Returns a pointer to the decoder. |
|
151 AbstractMediaDecoder* GetDecoder() { |
|
152 return mDecoder; |
|
153 } |
|
154 |
|
155 AudioData* DecodeToFirstAudioData(); |
|
156 VideoData* DecodeToFirstVideoData(); |
|
157 |
|
158 // Decodes samples until we reach frames required to play at time aTarget |
|
159 // (usecs). This also trims the samples to start exactly at aTarget, |
|
160 // by discarding audio samples and adjusting start times of video frames. |
|
161 nsresult DecodeToTarget(int64_t aTarget); |
|
162 |
|
163 MediaInfo GetMediaInfo() { return mInfo; } |
|
164 |
|
165 protected: |
|
166 |
|
167 // Reference to the owning decoder object. |
|
168 AbstractMediaDecoder* mDecoder; |
|
169 |
|
170 // Stores presentation info required for playback. |
|
171 MediaInfo mInfo; |
|
172 |
|
173 // Whether we should accept media that we know we can't play |
|
174 // directly, because they have a number of channel higher than |
|
175 // what we support. |
|
176 bool mIgnoreAudioOutputFormat; |
|
177 }; |
|
178 |
|
179 } // namespace mozilla |
|
180 |
|
181 #endif |