1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CAST_STANDALONE_SENDER_SIMULATED_CAPTURER_H_ 6 #define CAST_STANDALONE_SENDER_SIMULATED_CAPTURER_H_ 7 8 #include <stdint.h> 9 10 #include <string> 11 #include <vector> 12 13 #include "absl/types/optional.h" 14 #include "cast/standalone_sender/ffmpeg_glue.h" 15 #include "platform/api/time.h" 16 #include "util/alarm.h" 17 18 namespace openscreen { 19 namespace cast { 20 21 class Environment; 22 23 // Simulates live media capture by demuxing, decoding, and emitting a stream of 24 // frames from a file at normal (1X) speed. This is a base class containing 25 // common functionality. Typical usage: Instantiate one SimulatedAudioCapturer 26 // and one FileVideoStreamCapturer. 27 class SimulatedCapturer { 28 public: 29 // Interface for receiving end-of-stream and fatal error notifications. 30 class Observer { 31 public: 32 // Called once the end of the file has been reached and the |capturer| has 33 // halted. 34 virtual void OnEndOfFile(SimulatedCapturer* capturer) = 0; 35 36 // Called if a non-recoverable error occurs and the |capturer| has halted. 37 virtual void OnError(SimulatedCapturer* capturer, std::string message) = 0; 38 39 protected: 40 virtual ~Observer(); 41 }; 42 43 void SetPlaybackRate(double rate); 44 45 protected: 46 SimulatedCapturer(Environment* environment, 47 const char* path, 48 AVMediaType media_type, 49 Clock::time_point start_time, 50 Observer* observer); 51 52 virtual ~SimulatedCapturer(); 53 54 // Optionally overridden, to apply additional decoder context settings before 55 // avcodec_open2() is called. 56 virtual void SetAdditionalDecoderParameters(AVCodecContext* decoder_context); 57 58 // Performs any additional processing on the decoded frame (e.g., audio 59 // resampling), and returns any adjustments to the frame's capture time (e.g., 60 // to account for any buffering). If a fatal error occurs, absl::nullopt is 61 // returned. The default implementation does nothing. 62 // 63 // Mutating the |decoded_frame| is not allowed. If a subclass implementation 64 // wants to deliver different data (e.g., resampled audio), it must stash the 65 // data itself for the next DeliverDataToClient() call. 66 virtual absl::optional<Clock::duration> ProcessDecodedFrame( 67 const AVFrame& decoded_frame); 68 69 // Delivers the decoded frame data to the client. 70 virtual void DeliverDataToClient(const AVFrame& decoded_frame, 71 Clock::time_point capture_time) = 0; 72 73 // Called when any transient or fatal error occurs, generating an Error and 74 // scheduling a task to notify the Observer of it soon. 75 void OnError(const char* what, int av_errnum); 76 77 // Converts the given FFMPEG tick count into an approximate Clock::duration. 78 static Clock::duration ToApproximateClockDuration( 79 int64_t ticks, 80 const AVRational& time_base); 81 82 private: 83 // Reads the next frame from the file, sends it to the decoder, and schedules 84 // a future ConsumeNextDecodedFrame() call to continue processing. 85 void StartDecodingNextFrame(); 86 87 // Receives the next decoded frame and schedules media delivery to the client, 88 // and/or calls Observer::OnEndOfFile() if there are no more frames in the 89 // file. 90 void ConsumeNextDecodedFrame(); 91 92 const AVFormatContextUniquePtr format_context_; 93 const AVMediaType media_type_; // Audio or Video. 94 const Clock::time_point start_time_; 95 Observer* const observer_; 96 const AVPacketUniquePtr packet_; // Decoder input buffer. 97 const AVFrameUniquePtr decoded_frame_; // Decoder output frame. 98 int stream_index_ = -1; // Selected stream from the file. 99 AVCodecContextUniquePtr decoder_context_; 100 101 // The last frame's stream timestamp. This is used to detect bad stream 102 // timestamps in the file. 103 absl::optional<Clock::duration> last_frame_timestamp_; 104 105 // Used to schedule the next task to execute and when it should execute. There 106 // is only ever one task scheduled/running at any time. 107 Alarm next_task_; 108 109 // Used to determine playback rate. Currently, we only support "playing" 110 // at 1x speed, or "pausing" at 0x speed. 111 bool playback_rate_is_non_zero_ = true; 112 }; 113 114 // Emits the primary audio stream from a file. 115 class SimulatedAudioCapturer final : public SimulatedCapturer { 116 public: 117 class Client : public SimulatedCapturer::Observer { 118 public: 119 // Called to deliver more audio data as |interleaved_samples|, which 120 // contains |num_samples| tuples (i.e., multiply by the number of channels 121 // to determine the number of array elements). |capture_time| is used to 122 // synchronize the play-out of the first audio sample with respect to video 123 // frames. 124 virtual void OnAudioData(const float* interleaved_samples, 125 int num_samples, 126 Clock::time_point capture_time) = 0; 127 128 protected: 129 ~Client() override; 130 }; 131 132 // Constructor: |num_channels| and |sample_rate| specify the required audio 133 // format. If necessary, audio from the file will be resampled to match the 134 // required format. 135 SimulatedAudioCapturer(Environment* environment, 136 const char* path, 137 int num_channels, 138 int sample_rate, 139 Clock::time_point start_time, 140 Client* client); 141 142 ~SimulatedAudioCapturer() final; 143 144 private: 145 // Examines the audio format of the given |frame|, and ensures the resampler 146 // is initialized to take that as input. 147 bool EnsureResamplerIsInitializedFor(const AVFrame& frame); 148 149 // Resamples the current |SimulatedCapturer::decoded_frame()| into the 150 // required output format/channels/rate. The result is stored in 151 // |resampled_audio_| for the next DeliverDataToClient() call. 152 absl::optional<Clock::duration> ProcessDecodedFrame( 153 const AVFrame& decoded_frame) final; 154 155 // Called at the moment Client::OnAudioData() should be called to pass the 156 // |resampled_audio_|. 157 void DeliverDataToClient(const AVFrame& decoded_frame, 158 Clock::time_point capture_time) final; 159 160 const int num_channels_; // Output number of channels. 161 const int sample_rate_; // Output sample rate. 162 Client* const client_; 163 164 const SwrContextUniquePtr resampler_; 165 166 // Current resampler input audio parameters. 167 AVSampleFormat input_sample_format_ = AV_SAMPLE_FMT_NONE; 168 int input_sample_rate_; 169 uint64_t input_channel_layout_; // Opaque value used by resampler library. 170 171 std::vector<float> resampled_audio_; 172 }; 173 174 // Emits the primary video stream from a file. 175 class SimulatedVideoCapturer final : public SimulatedCapturer { 176 public: 177 class Client : public SimulatedCapturer::Observer { 178 public: 179 // Called to deliver the next video |frame|, which is always in I420 format. 180 // |capture_time| is used to synchronize the play-out of the video frame 181 // with respect to the audio track. 182 virtual void OnVideoFrame(const AVFrame& frame, 183 Clock::time_point capture_time) = 0; 184 185 protected: 186 ~Client() override; 187 }; 188 189 SimulatedVideoCapturer(Environment* environment, 190 const char* path, 191 Clock::time_point start_time, 192 Client* client); 193 194 ~SimulatedVideoCapturer() final; 195 196 private: 197 Client* const client_; 198 199 // Sets up the decoder to produce I420 format output. 200 void SetAdditionalDecoderParameters(AVCodecContext* decoder_context) final; 201 202 // Called at the moment Client::OnVideoFrame() should be called to provide the 203 // next video frame. 204 void DeliverDataToClient(const AVFrame& decoded_frame, 205 Clock::time_point capture_time) final; 206 }; 207 208 } // namespace cast 209 } // namespace openscreen 210 211 #endif // CAST_STANDALONE_SENDER_SIMULATED_CAPTURER_H_ 212