aboutsummaryrefslogtreecommitdiff
path: root/cast/standalone_receiver/decoder.h
diff options
context:
space:
mode:
Diffstat (limited to 'cast/standalone_receiver/decoder.h')
-rw-r--r--cast/standalone_receiver/decoder.h99
1 files changed, 99 insertions, 0 deletions
diff --git a/cast/standalone_receiver/decoder.h b/cast/standalone_receiver/decoder.h
new file mode 100644
index 00000000..1d4d0791
--- /dev/null
+++ b/cast/standalone_receiver/decoder.h
@@ -0,0 +1,99 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CAST_STANDALONE_RECEIVER_DECODER_H_
+#define CAST_STANDALONE_RECEIVER_DECODER_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/types/span.h"
+#include "cast/standalone_receiver/avcodec_glue.h"
+#include "cast/streaming/frame_id.h"
+
+namespace openscreen {
+namespace cast {
+
+// Wraps libavcodec to decode audio or video.
+class Decoder {
+ public:
+ // A buffer backed by storage that is compatible with FFMPEG (i.e., includes
+ // the required zero-padding).
+ class Buffer {
+ public:
+ Buffer();
+ ~Buffer();
+
+ void Resize(int new_size);
+ absl::Span<const uint8_t> GetSpan() const;
+ absl::Span<uint8_t> GetSpan();
+
+ private:
+ std::vector<uint8_t> buffer_;
+ };
+
+ // Interface for receiving decoded frames and/or errors.
+ class Client {
+ public:
+ virtual ~Client();
+
+ virtual void OnFrameDecoded(FrameId frame_id, const AVFrame& frame) = 0;
+ virtual void OnDecodeError(FrameId frame_id, std::string message) = 0;
+ virtual void OnFatalError(std::string message) = 0;
+
+ protected:
+ Client();
+ };
+
+ // |codec_name| should be the codec_name field from an OFFER message.
+ explicit Decoder(const std::string& codec_name);
+ ~Decoder();
+
+ Client* client() const { return client_; }
+ void set_client(Client* client) { client_ = client; }
+
+ // Starts decoding the data in |buffer|, which should be associated with the
+ // given |frame_id|. This will synchronously call Client::OnFrameDecoded()
+ // and/or Client::OnDecodeError() zero or more times with results. Note that
+ // some codecs will have data dependencies that require multiple encoded
+ // frame's data before the first decoded frame can be generated.
+ void Decode(FrameId frame_id, const Buffer& buffer);
+
+ private:
+ // Helper to initialize the FFMPEG decoder and supporting objects. Returns
+ // false if this failed (and the Client was notified).
+ bool Initialize();
+
+ // Helper to get the FrameId that is associated with the next frame coming out
+ // of the FFMPEG decoder.
+ FrameId DidReceiveFrameFromDecoder();
+
+ // Helper to handle a codec initialization error and notify the Client of the
+ // fatal error.
+ void HandleInitializationError(const char* what, int av_errnum);
+
+ // Called when any transient or fatal error occurs, generating an Error and
+ // notifying the Client of it.
+ void OnError(const char* what, int av_errnum, FrameId frame_id);
+
+ const std::string codec_name_;
+ AVCodec* codec_ = nullptr;
+ AVCodecParserContextUniquePtr parser_;
+ AVCodecContextUniquePtr context_;
+ AVPacketUniquePtr packet_;
+ AVFrameUniquePtr decoded_frame_;
+
+ Client* client_ = nullptr;
+
+ // Queue of frames that have been input to the libavcodec decoder, but which
+ // have not yet had output generated by it.
+ std::vector<FrameId> frames_decoding_;
+};
+
+} // namespace cast
+} // namespace openscreen
+
+#endif // CAST_STANDALONE_RECEIVER_DECODER_H_