1// Copyright 2014 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#include "chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.h"
6
7#include "base/logging.h"
8#include "chromecast/media/cma/base/decoder_buffer_base.h"
9#include "chromecast/media/cma/ipc/media_message.h"
10#include "chromecast/media/cma/ipc/media_message_type.h"
11#include "chromecast/media/cma/ipc_streamer/decrypt_config_marshaller.h"
12#include "media/base/decrypt_config.h"
13
14namespace chromecast {
15namespace media {
16
17namespace {
18const size_t kMaxFrameSize = 4 * 1024 * 1024;
19
20class DecoderBufferFromMsg : public DecoderBufferBase {
21 public:
22  explicit DecoderBufferFromMsg(scoped_ptr<MediaMessage> msg);
23
24  void Initialize();
25
26  // DecoderBufferBase implementation.
27  virtual base::TimeDelta timestamp() const OVERRIDE;
28  virtual const uint8* data() const OVERRIDE;
29  virtual uint8* writable_data() const OVERRIDE;
30  virtual int data_size() const OVERRIDE;
31  virtual const ::media::DecryptConfig* decrypt_config() const OVERRIDE;
32  virtual bool end_of_stream() const OVERRIDE;
33
34 private:
35  virtual ~DecoderBufferFromMsg();
36
37  // Indicates whether this is an end of stream frame.
38  bool is_eos_;
39
40  // Frame timestamp.
41  base::TimeDelta pts_;
42
43  // CENC parameters.
44  scoped_ptr< ::media::DecryptConfig> decrypt_config_;
45
46  // Size of the frame.
47  int data_size_;
48
49  // Keeps the message since frame data is not copied.
50  scoped_ptr<MediaMessage> msg_;
51  uint8* data_;
52
53  DISALLOW_COPY_AND_ASSIGN(DecoderBufferFromMsg);
54};
55
56DecoderBufferFromMsg::DecoderBufferFromMsg(
57    scoped_ptr<MediaMessage> msg)
58    : msg_(msg.Pass()),
59      is_eos_(true),
60      data_(NULL) {
61  CHECK(msg_);
62}
63
64DecoderBufferFromMsg::~DecoderBufferFromMsg() {
65}
66
67void DecoderBufferFromMsg::Initialize() {
68  CHECK_EQ(msg_->type(), FrameMediaMsg);
69
70  CHECK(msg_->ReadPod(&is_eos_));
71  if (is_eos_)
72    return;
73
74  int64 pts_internal = 0;
75  CHECK(msg_->ReadPod(&pts_internal));
76  pts_ = base::TimeDelta::FromInternalValue(pts_internal);
77
78  bool has_decrypt_config = false;
79  CHECK(msg_->ReadPod(&has_decrypt_config));
80  if (has_decrypt_config)
81    decrypt_config_.reset(DecryptConfigMarshaller::Read(msg_.get()).release());
82
83  CHECK(msg_->ReadPod(&data_size_));
84  CHECK_GT(data_size_, 0);
85  CHECK_LT(data_size_, kMaxFrameSize);
86
87  // Get a pointer to the frame data inside the message.
88  // Avoid copying the frame data here.
89  data_ = static_cast<uint8*>(msg_->GetWritableBuffer(data_size_));
90  CHECK(data_);
91
92  if (decrypt_config_) {
93    uint32 subsample_total_size = 0;
94    for (size_t k = 0; k < decrypt_config_->subsamples().size(); k++) {
95      subsample_total_size += decrypt_config_->subsamples()[k].clear_bytes;
96      subsample_total_size += decrypt_config_->subsamples()[k].cypher_bytes;
97    }
98    CHECK_EQ(subsample_total_size, data_size_);
99  }
100}
101
102base::TimeDelta DecoderBufferFromMsg::timestamp() const {
103  return pts_;
104}
105
106const uint8* DecoderBufferFromMsg::data() const {
107  CHECK(msg_->IsSerializedMsgAvailable());
108  return data_;
109}
110
111uint8* DecoderBufferFromMsg::writable_data() const {
112  CHECK(msg_->IsSerializedMsgAvailable());
113  return data_;
114}
115
116int DecoderBufferFromMsg::data_size() const {
117  return data_size_;
118}
119
120const ::media::DecryptConfig* DecoderBufferFromMsg::decrypt_config() const {
121  return decrypt_config_.get();
122}
123
124bool DecoderBufferFromMsg::end_of_stream() const {
125  return is_eos_;
126}
127
128}  // namespace
129
130// static
131void DecoderBufferBaseMarshaller::Write(
132    const scoped_refptr<DecoderBufferBase>& buffer,
133    MediaMessage* msg) {
134  CHECK(msg->WritePod(buffer->end_of_stream()));
135  if (buffer->end_of_stream())
136    return;
137
138  CHECK(msg->WritePod(buffer->timestamp().ToInternalValue()));
139
140  bool has_decrypt_config =
141      (buffer->decrypt_config() != NULL &&
142       buffer->decrypt_config()->iv().size() > 0);
143  CHECK(msg->WritePod(has_decrypt_config));
144  if (has_decrypt_config)
145    DecryptConfigMarshaller::Write(*buffer->decrypt_config(), msg);
146
147  CHECK(msg->WritePod(buffer->data_size()));
148  CHECK(msg->WriteBuffer(buffer->data(), buffer->data_size()));
149}
150
151// static
152scoped_refptr<DecoderBufferBase> DecoderBufferBaseMarshaller::Read(
153    scoped_ptr<MediaMessage> msg) {
154  scoped_refptr<DecoderBufferFromMsg> buffer(
155      new DecoderBufferFromMsg(msg.Pass()));
156  buffer->Initialize();
157  return buffer;
158}
159
160}  // namespace media
161}  // namespace chromecast
162