[go: nahoru, domu]

Replace StreamStatusChanged callback with async track switching

Allow the pipeline to control the entire track switch process without
    the media source communicating directly with the renderer.

    WMPL | pipeline | demuxer | demuxer_stream | renderer | video/audio_renderer
    ───────────────────────────Old Control Flow─────────────────────────────────
         |          |         |                |          |
     switch_track   |         |                |          |
      --------->    |         |                |          |
         |    switch track    |                |          |
         |     --------->     |                |          |
         |          | disable/enable stream    |          |
         |          |      ----------->        |          |
    ───────────────────────Sometime in the future───────────────────────────────
         |          |         |               read from stream
         |          |         |        <-----------------------------
         |          |         |                |End of stream
         |          |         |        ----------------------------->
         |          |         |                |      OnStreamStatus
         |          |         |                |    <----------------
         |          |         |                |   Flush/Restart/Reset
         |          |         |                |    ---------------->
         |          |         |                | OnBufferingStateChange
         |          |         |                |    <----------------
         |          | OnBufferingStateChange   |          |
         |    <--------------------------------------     |
    OnBufferingStateChange    |                |          |
    <----------     |         |                |          |

    ───────────────────────────New Control Flow─────────────────────────────────
    WMPL | pipeline | demuxer | demuxer_stream | renderer | video/audio_renderer
         |          |         |                |          |
     switch_track   |         |                |          |
      --------->    |         |                |          |
         |    switch track    |                |          |
         |     --------->     |                |          |
         |          | disable/enable stream    |          |
         |          |      ----------->        |          |
         |   active streams   |                |          |
         |     <---------     |                |          |
         |          |        switch track      |          |
         |     -------------------------------------->    |
         |          |         |                |    Flush/Restart/Reset
         |          |         |                |     --------------->
         |          |  Notify pipeline of completed track change
         |     <-----------------------------------------------------
    ───────────────────────Sometime in the future───────────────────────────────
         |          |         |                | OnBufferingStateChange
         |          |         |                |    <----------------
         |          | OnBufferingStateChange   |          |
         |    <--------------------------------------     |
    OnBufferingStateChange    |                |          |
    <----------     |         |                |          |

    In the new control flow the pipeline is able to control both the demuxer
    and the renderer, instead of controlling the demuxer and waiting for the
    renderer to act on it's own.


Bug: 709302
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: Iafc862e79f5afc1d3a6ea3400c03decd0ce91d27
Reviewed-on: https://chromium-review.googlesource.com/899843
Commit-Queue: Ted Meyer <tmathmeyer@chromium.org>
Reviewed-by: Sergey Volk <servolk@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Dan Sanders <sandersd@chromium.org>
Reviewed-by: Xiangjun Zhang <xjz@chromium.org>
Reviewed-by: Yuri Wiitala <miu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551901}
diff --git a/media/renderers/renderer_impl.h b/media/renderers/renderer_impl.h
index cd73bf26..d50c928 100644
--- a/media/renderers/renderer_impl.h
+++ b/media/renderers/renderer_impl.h
@@ -62,6 +62,12 @@
   void SetPlaybackRate(double playback_rate) final;
   void SetVolume(float volume) final;
   base::TimeDelta GetMediaTime() final;
+  void OnSelectedVideoTracksChanged(
+      const std::vector<DemuxerStream*>& enabled_tracks,
+      base::OnceClosure change_completed_cb) override;
+  void OnEnabledAudioTracksChanged(
+      const std::vector<DemuxerStream*>& enabled_tracks,
+      base::OnceClosure change_completed_cb) override;
 
   // Helper functions for testing purposes. Must be called before Initialize().
   void DisableUnderflowForTesting();
@@ -106,25 +112,24 @@
   void FlushVideoRenderer();
   void OnVideoRendererFlushDone();
 
-  // This function notifies the renderer that the status of the demuxer |stream|
-  // has been changed, the new status is |enabled| and the change occured while
-  // playback position was |time|.
-  void OnStreamStatusChanged(DemuxerStream* stream,
-                             bool enabled,
-                             base::TimeDelta time);
-
   // Reinitialize audio/video renderer during a demuxer stream switching. The
   // renderer must be flushed first, and when the re-init is completed the
   // corresponding callback will be invoked to restart playback.
   // The |stream| parameter specifies the new demuxer stream, and the |time|
   // parameter specifies the time on media timeline where the switch occured.
-  void ReinitializeAudioRenderer(DemuxerStream* stream, base::TimeDelta time);
+  void ReinitializeAudioRenderer(DemuxerStream* stream,
+                                 base::TimeDelta time,
+                                 base::OnceClosure reinitialize_completed_cb);
   void OnAudioRendererReinitialized(DemuxerStream* stream,
                                     base::TimeDelta time,
+                                    base::OnceClosure reinitialize_completed_cb,
                                     PipelineStatus status);
-  void ReinitializeVideoRenderer(DemuxerStream* stream, base::TimeDelta time);
+  void ReinitializeVideoRenderer(DemuxerStream* stream,
+                                 base::TimeDelta time,
+                                 base::OnceClosure restart_completed_cb);
   void OnVideoRendererReinitialized(DemuxerStream* stream,
                                     base::TimeDelta time,
+                                    base::OnceClosure restart_completed_cb,
                                     PipelineStatus status);
 
   // Restart audio/video renderer playback after a demuxer stream switch or
@@ -134,8 +139,18 @@
   // needs to be restarted. It is necessary for demuxers with independent
   // streams (e.g. MSE / ChunkDemuxer) to synchronize data reading between those
   // streams.
-  void RestartAudioRenderer(DemuxerStream* stream, base::TimeDelta time);
-  void RestartVideoRenderer(DemuxerStream* stream, base::TimeDelta time);
+  void RestartAudioRenderer(DemuxerStream* stream,
+                            base::TimeDelta time,
+                            base::OnceClosure restart_completed_cb);
+  void RestartVideoRenderer(DemuxerStream* stream,
+                            base::TimeDelta time,
+                            base::OnceClosure restart_completed_cb);
+
+  // Fix state booleans after the stream switching is finished.
+  void CleanUpTrackChange(base::RepeatingClosure on_finished,
+                          bool* pending_change,
+                          bool* ended,
+                          bool* playing);
 
   // Callback executed by filters to update statistics.
   void OnStatisticsUpdate(const PipelineStatistics& stats);
@@ -217,6 +232,8 @@
   // Whether we've received the audio/video ended events.
   bool audio_ended_;
   bool video_ended_;
+  bool audio_playing_;
+  bool video_playing_;
 
   CdmContext* cdm_context_;
 
@@ -238,21 +255,10 @@
   // TODO(servolk): Get rid of the lock and replace restarting_audio_ with
   // std::atomic<bool> when atomics are unbanned in Chromium.
   base::Lock restarting_audio_lock_;
-  bool restarting_audio_ = false;
+  bool pending_audio_track_change_ = false;
   base::TimeDelta restarting_audio_time_ = kNoTimestamp;
 
-  bool restarting_video_ = false;
-
-  // Flush operations and media track status changes must be serialized to avoid
-  // interfering with each other. This list will hold a list of postponed
-  // actions that need to be completed after the current async operation is
-  // completed.
-  std::list<base::Closure> pending_actions_;
-
-  // Pending flush indicates that a track change is in the middle of a Flush and
-  // that another one can't be scheduled at this time. Instead it should be
-  // added to |pending_actions_|.
-  bool pending_flush_for_stream_change_ = false;
+  bool pending_video_track_change_ = false;
 
   base::WeakPtr<RendererImpl> weak_this_;
   base::WeakPtrFactory<RendererImpl> weak_factory_;