зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1464268 - Fix MediaRecorder comments. r=bryce
Differential Revision: https://phabricator.services.mozilla.com/D95729
This commit is contained in:
Родитель
d40bae9b5a
Коммит
56768028df
|
@ -545,37 +545,27 @@ void SelectBitrates(uint32_t aBitsPerSecond, uint8_t aNumVideoTracks,
|
|||
* In original design, all recording context is stored in MediaRecorder, which
|
||||
* causes a problem if someone calls MediaRecorder::Stop and
|
||||
* MediaRecorder::Start quickly. To prevent blocking main thread, media encoding
|
||||
* is executed in a second thread, named as Read Thread. For the same reason, we
|
||||
* do not wait Read Thread shutdown in MediaRecorder::Stop. If someone call
|
||||
* MediaRecorder::Start before Read Thread shutdown, the same recording context
|
||||
* in MediaRecorder might be access by two Reading Threads, which cause a
|
||||
* problem. In the new design, we put recording context into Session object,
|
||||
* including Read Thread. Each Session has its own recording context and Read
|
||||
* Thread, problem is been resolved.
|
||||
*
|
||||
* Life cycle of a Session object.
|
||||
* 1) Initialization Stage (in main thread)
|
||||
* Setup media tracks in MTG, and bind MediaEncoder with Source Stream when
|
||||
* mStream is available. Resource allocation, such as encoded data cache buffer
|
||||
* and MediaEncoder. Create read thread. Automatically switch to Extract stage
|
||||
* in the end of this stage. 2) Extract Stage (in Read Thread) Pull encoded A/V
|
||||
* frames from MediaEncoder, dispatch to OnDataAvailable handler. Unless a
|
||||
* client calls Session::Stop, Session object keeps stay in this stage. 3)
|
||||
* Destroy Stage (in main thread) Switch from Extract stage to Destroy stage by
|
||||
* calling Session::Stop. Release session resource and remove associated tracks
|
||||
* from MTG.
|
||||
* is executed in a second thread, named encoder thread. For the same reason, we
|
||||
* do not await encoder thread shutdown in MediaRecorder::Stop.
|
||||
* If someone calls MediaRecorder::Start before encoder thread shutdown, the
|
||||
* same recording context in MediaRecorder might be accessed by two distinct
|
||||
* encoder threads, which would be racy. With the recording context, including
|
||||
* the encoder thread, in a Session object the problem is solved.
|
||||
*
|
||||
* Lifetime of MediaRecorder and Session objects.
|
||||
* 1) MediaRecorder creates a Session in MediaRecorder::Start function and holds
|
||||
* a reference to Session. Then the Session registers itself to a
|
||||
* ShutdownBlocker and also holds a reference to MediaRecorder.
|
||||
* 1) MediaRecorder creates a Session in MediaRecorder::Start() and holds
|
||||
* a reference to it. Then the Session registers itself to a ShutdownBlocker
|
||||
* and also holds a reference to MediaRecorder.
|
||||
* Therefore, the reference dependency in gecko is:
|
||||
* ShutdownBlocker -> Session <-> MediaRecorder, note that there is a cycle
|
||||
* reference between Session and MediaRecorder.
|
||||
* 2) A Session is destroyed after MediaRecorder::Stop has been called _and_ all
|
||||
* encoded media data has been passed to OnDataAvailable handler. 3)
|
||||
* MediaRecorder::Stop is called by user or the document is going to inactive or
|
||||
* invisible.
|
||||
* 2) A Session is destroyed after Session::DoSessionEndTask() has been called
|
||||
* _and_ all encoded media data has been passed to OnDataAvailable handler.
|
||||
* In some cases the encoded media can be discarded before being passed to
|
||||
* the OnDataAvailable handler.
|
||||
* 3) Session::DoSessionEndTask is called by an application through
|
||||
* MediaRecorder::Stop(), from a MediaEncoder Shutdown notification, from the
|
||||
* document going inactive or invisible, or from the ShutdownBlocker.
|
||||
*/
|
||||
class MediaRecorder::Session : public PrincipalChangeObserver<MediaStreamTrack>,
|
||||
public DOMMediaStream::TrackListener {
|
||||
|
|
|
@ -31,17 +31,23 @@ class DOMException;
|
|||
|
||||
/**
|
||||
* Implementation of
|
||||
* https://dvcs.w3.org/hg/dap/raw-file/default/media-stream-capture/MediaRecorder.html
|
||||
* The MediaRecorder accepts a mediaStream as input source passed from UA. When
|
||||
* recorder starts, a MediaEncoder will be created and accept the mediaStream as
|
||||
* input source. Encoder will get the raw data by track data changes, encode it
|
||||
* by selected MIME Type, then store the encoded in a MutableBlobStorage object.
|
||||
* The encoded data will be extracted on every timeslice passed from Start
|
||||
* function call or by RequestData function. Thread model: When the recorder
|
||||
* starts, it creates a "Media Encoder" thread to read data from MediaEncoder
|
||||
* object and store buffer in MutableBlobStorage object. Also extract the
|
||||
* encoded data and create blobs on every timeslice passed from start function
|
||||
* or RequestData function called by UA.
|
||||
* https://w3c.github.io/mediacapture-record/MediaRecorder.html
|
||||
*
|
||||
* The MediaRecorder accepts a MediaStream as input passed from an application.
|
||||
* When the MediaRecorder starts, a MediaEncoder will be created and accepts the
|
||||
* MediaStreamTracks in the MediaStream as input source. For each track it
|
||||
* creates a TrackEncoder.
|
||||
*
|
||||
* The MediaEncoder automatically encodes and muxes data from the tracks by the
|
||||
* given MIME type, then it stores this data into a MutableBlobStorage object.
|
||||
* When a timeslice is set and the MediaEncoder has stored enough data to fill
|
||||
* the timeslice, it extracts a Blob from the storage and passes it to
|
||||
* MediaRecorder. On RequestData() or Stop(), the MediaEncoder extracts the blob
|
||||
* from the storage and returns it to MediaRecorder through a MozPromise.
|
||||
*
|
||||
* Thread model: When the recorder starts, it creates a worker thread (called
|
||||
* the encoder thread) that does all the heavy lifting - encoding, time keeping,
|
||||
* muxing.
|
||||
*/
|
||||
|
||||
class MediaRecorder final : public DOMEventTargetHelper,
|
||||
|
@ -61,13 +67,9 @@ class MediaRecorder final : public DOMEventTargetHelper,
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaRecorder, DOMEventTargetHelper)
|
||||
|
||||
// WebIDL
|
||||
// Start recording. If timeSlice has been provided, mediaRecorder will
|
||||
// raise a dataavailable event containing the Blob of collected data on every
|
||||
// timeSlice milliseconds. If timeSlice isn't provided, UA should call the
|
||||
// RequestData to obtain the Blob data, also set the mTimeSlice to zero.
|
||||
// Start recording.
|
||||
void Start(const Optional<uint32_t>& timeSlice, ErrorResult& aResult);
|
||||
// Stop the recording activiy. Including stop the Media Encoder thread,
|
||||
// un-hook the mediaStreamListener to encoder.
|
||||
// Stop recording.
|
||||
void Stop(ErrorResult& aResult);
|
||||
// Pause a recording.
|
||||
void Pause(ErrorResult& aResult);
|
||||
|
|
Загрузка…
Ссылка в новой задаче