1 // Copyright 2019 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_RECEIVER_DECODER_H_ 6 #define CAST_STANDALONE_RECEIVER_DECODER_H_ 7 8 #include <stdint.h> 9 10 #include <string> 11 #include <vector> 12 13 #include "absl/types/span.h" 14 #include "cast/standalone_receiver/avcodec_glue.h" 15 #include "cast/streaming/frame_id.h" 16 17 namespace openscreen { 18 namespace cast { 19 20 // Wraps libavcodec to decode audio or video. 21 class Decoder { 22 public: 23 // A buffer backed by storage that is compatible with FFMPEG (i.e., includes 24 // the required zero-padding). 25 class Buffer { 26 public: 27 Buffer(); 28 ~Buffer(); 29 30 void Resize(int new_size); 31 absl::Span<const uint8_t> GetSpan() const; 32 absl::Span<uint8_t> GetSpan(); 33 34 private: 35 std::vector<uint8_t> buffer_; 36 }; 37 38 // Interface for receiving decoded frames and/or errors. 39 class Client { 40 public: 41 42 virtual void OnFrameDecoded(FrameId frame_id, const AVFrame& frame) = 0; 43 virtual void OnDecodeError(FrameId frame_id, std::string message) = 0; 44 virtual void OnFatalError(std::string message) = 0; 45 46 protected: 47 Client(); 48 virtual ~Client(); 49 }; 50 51 // |codec_name| should be the codec_name field from an OFFER message. 52 explicit Decoder(const std::string& codec_name); 53 ~Decoder(); 54 client()55 Client* client() const { return client_; } set_client(Client * client)56 void set_client(Client* client) { client_ = client; } 57 58 // Starts decoding the data in |buffer|, which should be associated with the 59 // given |frame_id|. This will synchronously call Client::OnFrameDecoded() 60 // and/or Client::OnDecodeError() zero or more times with results. Note that 61 // some codecs will have data dependencies that require multiple encoded 62 // frame's data before the first decoded frame can be generated. 63 void Decode(FrameId frame_id, const Buffer& buffer); 64 65 private: 66 // Helper to initialize the FFMPEG decoder and supporting objects. Returns 67 // false if this failed (and the Client was notified). 68 bool Initialize(); 69 70 // Helper to get the FrameId that is associated with the next frame coming out 71 // of the FFMPEG decoder. 72 FrameId DidReceiveFrameFromDecoder(); 73 74 // Helper to handle a codec initialization error and notify the Client of the 75 // fatal error. 76 void HandleInitializationError(const char* what, int av_errnum); 77 78 // Called when any transient or fatal error occurs, generating an Error and 79 // notifying the Client of it. 80 void OnError(const char* what, int av_errnum, FrameId frame_id); 81 82 const std::string codec_name_; 83 AVCodec* codec_ = nullptr; 84 AVCodecParserContextUniquePtr parser_; 85 AVCodecContextUniquePtr context_; 86 AVPacketUniquePtr packet_; 87 AVFrameUniquePtr decoded_frame_; 88 89 Client* client_ = nullptr; 90 91 // Queue of frames that have been input to the libavcodec decoder, but which 92 // have not yet had output generated by it. 93 std::vector<FrameId> frames_decoding_; 94 }; 95 96 } // namespace cast 97 } // namespace openscreen 98 99 #endif // CAST_STANDALONE_RECEIVER_DECODER_H_ 100