1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
// Copyright 2016 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.
#include "media/mojo/common/mojo_shared_buffer_video_frame.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
namespace media {
// static
scoped_refptr<MojoSharedBufferVideoFrame>
MojoSharedBufferVideoFrame::CreateDefaultI420(const gfx::Size& dimensions,
base::TimeDelta timestamp) {
const VideoPixelFormat format = PIXEL_FORMAT_I420;
const gfx::Rect visible_rect(dimensions);
// Since we're allocating memory for the new frame, pad the requested
// size if necessary so that the requested size does line up on sample
// boundaries. See related discussion in VideoFrame::CreateFrameInternal().
const gfx::Size coded_size = DetermineAlignedSize(format, dimensions);
if (!IsValidConfig(format, STORAGE_MOJO_SHARED_BUFFER, coded_size,
visible_rect, dimensions)) {
LOG(DFATAL) << __FUNCTION__ << " Invalid config. "
<< ConfigToString(format, STORAGE_MOJO_SHARED_BUFFER,
dimensions, visible_rect, dimensions);
return nullptr;
}
// Allocate a shared memory buffer big enough to hold the desired frame.
const size_t allocation_size = VideoFrame::AllocationSize(format, coded_size);
mojo::ScopedSharedBufferHandle handle;
const MojoResult result =
mojo::CreateSharedBuffer(nullptr, allocation_size, &handle);
if (result != MOJO_RESULT_OK)
return nullptr;
// Create and initialize the frame. As this is I420 format, the U and V
// planes have samples for each 2x2 block. The memory is laid out as follows:
// - Yplane, full size (each element represents a 1x1 block)
// - Uplane, quarter size (each element represents a 2x2 block)
// - Vplane, quarter size (each element represents a 2x2 block)
DCHECK((coded_size.width() % 2 == 0) && (coded_size.height() % 2 == 0));
return Create(format, coded_size, visible_rect, dimensions, std::move(handle),
allocation_size, 0 /* y_offset */, coded_size.GetArea(),
coded_size.GetArea() * 5 / 4, coded_size.width(),
coded_size.width() / 2, coded_size.width() / 2, timestamp);
}
// static
scoped_refptr<MojoSharedBufferVideoFrame> MojoSharedBufferVideoFrame::Create(
VideoPixelFormat format,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
mojo::ScopedSharedBufferHandle handle,
size_t data_size,
size_t y_offset,
size_t u_offset,
size_t v_offset,
int32_t y_stride,
int32_t u_stride,
int32_t v_stride,
base::TimeDelta timestamp) {
if (!IsValidConfig(format, STORAGE_MOJO_SHARED_BUFFER, coded_size,
visible_rect, natural_size)) {
LOG(DFATAL) << __FUNCTION__ << " Invalid config. "
<< ConfigToString(format, STORAGE_MOJO_SHARED_BUFFER,
coded_size, visible_rect, natural_size);
return nullptr;
}
// Now allocate the frame and initialize it.
scoped_refptr<MojoSharedBufferVideoFrame> frame(
new MojoSharedBufferVideoFrame(format, coded_size, visible_rect,
natural_size, std::move(handle), data_size,
timestamp));
if (!frame->Init(y_stride, u_stride, v_stride, y_offset, u_offset, v_offset))
return nullptr;
return frame;
}
MojoSharedBufferVideoFrame::MojoSharedBufferVideoFrame(
VideoPixelFormat format,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
mojo::ScopedSharedBufferHandle handle,
size_t mapped_size,
base::TimeDelta timestamp)
: VideoFrame(format,
STORAGE_MOJO_SHARED_BUFFER,
coded_size,
visible_rect,
natural_size,
timestamp),
shared_buffer_handle_(std::move(handle)),
shared_buffer_size_(mapped_size),
shared_buffer_data_(nullptr) {
DCHECK(shared_buffer_handle_.is_valid());
}
bool MojoSharedBufferVideoFrame::Init(int32_t y_stride,
int32_t u_stride,
int32_t v_stride,
size_t y_offset,
size_t u_offset,
size_t v_offset) {
DCHECK(!shared_buffer_data_);
void* memory = nullptr;
const MojoResult result =
mojo::MapBuffer(shared_buffer_handle_.get(), 0 /* offset */,
shared_buffer_size_, &memory, MOJO_MAP_BUFFER_FLAG_NONE);
if (result != MOJO_RESULT_OK || !memory)
return false;
shared_buffer_data_ = static_cast<uint8_t*>(memory);
set_stride(kYPlane, y_stride);
set_stride(kUPlane, u_stride);
set_stride(kVPlane, v_stride);
offsets_[kYPlane] = y_offset;
offsets_[kUPlane] = u_offset;
offsets_[kVPlane] = v_offset;
set_data(kYPlane, shared_buffer_data_ + y_offset);
set_data(kUPlane, shared_buffer_data_ + u_offset);
set_data(kVPlane, shared_buffer_data_ + v_offset);
return true;
}
MojoSharedBufferVideoFrame::~MojoSharedBufferVideoFrame() {
// If MapBuffer() was called, we need to have a matching call to unmap it.
if (shared_buffer_data_) {
const MojoResult result = mojo::UnmapBuffer(shared_buffer_data_);
ALLOW_UNUSED_LOCAL(result);
DCHECK_EQ(result, MOJO_RESULT_OK);
}
// Call |mojo_shared_buffer_done_cb_| to take ownership of
// |shared_buffer_handle_|.
if (!mojo_shared_buffer_done_cb_.is_null())
mojo_shared_buffer_done_cb_.Run(std::move(shared_buffer_handle_),
shared_buffer_size_);
}
size_t MojoSharedBufferVideoFrame::PlaneOffset(size_t plane) const {
DCHECK(IsValidPlane(plane, format()));
return offsets_[plane];
}
void MojoSharedBufferVideoFrame::SetMojoSharedBufferDoneCB(
const MojoSharedBufferDoneCB& mojo_shared_buffer_done_cb) {
mojo_shared_buffer_done_cb_ = mojo_shared_buffer_done_cb;
}
const mojo::SharedBufferHandle& MojoSharedBufferVideoFrame::Handle() const {
return shared_buffer_handle_.get();
}
size_t MojoSharedBufferVideoFrame::MappedSize() const {
return shared_buffer_size_;
}
} // namespace media
|