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.
5 #include "chromecast/media/cma/ipc/media_message.h"
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "chromecast/media/cma/ipc/media_memory_chunk.h"
13 namespace chromecast
{
17 scoped_ptr
<MediaMessage
> MediaMessage::CreateDummyMessage(
19 return scoped_ptr
<MediaMessage
>(
20 new MediaMessage(type
, std::numeric_limits
<size_t>::max()));
24 scoped_ptr
<MediaMessage
> MediaMessage::CreateMessage(
26 const MemoryAllocatorCB
& memory_allocator
,
27 size_t msg_content_capacity
) {
28 size_t msg_size
= minimum_msg_size() + msg_content_capacity
;
30 // Make the message size a multiple of the alignment
31 // so that if we have proper alignment for array of messages.
32 size_t end_alignment
= msg_size
% ALIGNOF(SerializedMsg
);
33 if (end_alignment
!= 0)
34 msg_size
+= ALIGNOF(SerializedMsg
) - end_alignment
;
36 scoped_ptr
<MediaMemoryChunk
> memory(memory_allocator
.Run(msg_size
));
38 return scoped_ptr
<MediaMessage
>();
40 return scoped_ptr
<MediaMessage
>(new MediaMessage(type
, memory
.Pass()));
44 scoped_ptr
<MediaMessage
> MediaMessage::CreateMessage(
46 scoped_ptr
<MediaMemoryChunk
> memory
) {
47 return scoped_ptr
<MediaMessage
>(new MediaMessage(type
, memory
.Pass()));
51 scoped_ptr
<MediaMessage
> MediaMessage::MapMessage(
52 scoped_ptr
<MediaMemoryChunk
> memory
) {
53 return scoped_ptr
<MediaMessage
>(new MediaMessage(memory
.Pass()));
56 MediaMessage::MediaMessage(uint32 type
, size_t msg_size
)
57 : is_dummy_msg_(true),
58 cached_header_(&cached_msg_
.header
),
60 msg_read_only_(&cached_msg_
),
62 cached_header_
->size
= msg_size
;
63 cached_header_
->type
= type
;
64 cached_header_
->content_size
= 0;
67 MediaMessage::MediaMessage(uint32 type
, scoped_ptr
<MediaMemoryChunk
> memory
)
68 : is_dummy_msg_(false),
69 cached_header_(&cached_msg_
.header
),
70 msg_(static_cast<SerializedMsg
*>(memory
->data())),
75 CHECK_GE(mem_
->size(), minimum_msg_size());
77 // Check memory alignment:
78 // needed to cast properly |msg_dst| to a SerializedMsg.
80 reinterpret_cast<uintptr_t>(mem_
->data()) % ALIGNOF(SerializedMsg
), 0u);
82 // Make sure that |mem_->data()| + |mem_->size()| is also aligned correctly.
83 // This is needed if we append a second serialized message next to this one.
84 // The second serialized message must be aligned correctly.
85 // It is similar to what a compiler is doing for arrays of structures.
86 CHECK_EQ(mem_
->size() % ALIGNOF(SerializedMsg
), 0u);
88 cached_header_
->size
= mem_
->size();
89 cached_header_
->type
= type
;
90 cached_header_
->content_size
= 0;
91 msg_
->header
= *cached_header_
;
94 MediaMessage::MediaMessage(scoped_ptr
<MediaMemoryChunk
> memory
)
95 : is_dummy_msg_(false),
96 cached_header_(&cached_msg_
.header
),
98 msg_read_only_(static_cast<SerializedMsg
*>(memory
->data())),
101 CHECK(mem_
->valid());
103 // Check memory alignment.
105 reinterpret_cast<uintptr_t>(mem_
->data()) % ALIGNOF(SerializedMsg
), 0u);
107 // Cache the message header which cannot be modified while reading.
108 CHECK_GE(mem_
->size(), minimum_msg_size());
109 *cached_header_
= msg_read_only_
->header
;
110 CHECK_GE(cached_header_
->size
, minimum_msg_size());
112 // Make sure if we have 2 consecutive serialized messages in memory,
113 // the 2nd message is also aligned correctly.
114 CHECK_EQ(cached_header_
->size
% ALIGNOF(SerializedMsg
), 0u);
116 size_t max_content_size
= cached_header_
->size
- minimum_msg_size();
117 CHECK_LE(cached_header_
->content_size
, max_content_size
);
120 MediaMessage::~MediaMessage() {
123 bool MediaMessage::IsSerializedMsgAvailable() const {
124 return !is_dummy_msg_
&& mem_
->valid();
127 bool MediaMessage::WriteBuffer(const void* src
, size_t size
) {
128 // No message to write into.
132 // The underlying memory was invalidated.
133 if (!is_dummy_msg_
&& !mem_
->valid())
136 size_t max_content_size
= cached_header_
->size
- minimum_msg_size();
137 if (cached_header_
->content_size
+ size
> max_content_size
) {
138 cached_header_
->content_size
= max_content_size
;
139 msg_
->header
.content_size
= cached_header_
->content_size
;
143 // Write the message only for non-dummy messages.
144 if (!is_dummy_msg_
) {
145 uint8
* wr_ptr
= &msg_
->content
+ cached_header_
->content_size
;
146 memcpy(wr_ptr
, src
, size
);
149 cached_header_
->content_size
+= size
;
150 msg_
->header
.content_size
= cached_header_
->content_size
;
154 bool MediaMessage::ReadBuffer(void* dst
, size_t size
) {
155 // No read possible for a dummy message.
159 // The underlying memory was invalidated.
163 if (rd_offset_
+ size
> cached_header_
->content_size
) {
164 rd_offset_
= cached_header_
->content_size
;
168 const uint8
* rd_ptr
= &msg_read_only_
->content
+ rd_offset_
;
169 memcpy(dst
, rd_ptr
, size
);
174 void* MediaMessage::GetWritableBuffer(size_t size
) {
175 // No read possible for a dummy message.
179 // The underlying memory was invalidated.
183 if (rd_offset_
+ size
> cached_header_
->content_size
) {
184 rd_offset_
= cached_header_
->content_size
;
188 uint8
* rd_ptr
= &msg_read_only_
->content
+ rd_offset_
;
193 const void* MediaMessage::GetBuffer(size_t size
) {
194 return GetWritableBuffer(size
);
198 } // namespace chromecast