(storage_type == VideoFrame::STORAGE_UNOWNED_MEMORY ||
storage_type == VideoFrame::STORAGE_OWNED_MEMORY ||
storage_type == VideoFrame::STORAGE_SHMEM ||
+#if defined(TIZEN_TBM_SUPPORT)
+ storage_type == VideoFrame::STORAGE_TBM_SURFACE ||
+#endif
storage_type == VideoFrame::STORAGE_MOJO_SHARED_BUFFER);
}
frame->buffer_handle_ = handle;
return frame;
}
+
+scoped_refptr<VideoFrame> VideoFrame::WrapTBMInterProcessBuffer(
+ const gfx::Size& size,
+ base::TimeDelta timestamp,
+ gfx::TbmBufferHandle handle,
+ const StorageType storage) {
+ const VideoPixelFormat format = PIXEL_FORMAT_TBM_INTER_PROCESS_BUFFER;
+
+ const gfx::Rect visible_rect = gfx::Rect(size);
+ if (!IsValidConfig(format, storage, size, visible_rect, size)) {
+ DLOG(ERROR) << __FUNCTION__ << " WrapTBMInterProcessBuffer Invalid config."
+ << ConfigToString(format, storage, size, visible_rect, size);
+ return nullptr;
+ }
+
+ auto layout = VideoFrameLayout::CreateWithStrides(
+ format, size, {handle.strides[0], handle.strides[1]});
+ if (!layout) {
+ DLOG(ERROR) << "Invalid layout.";
+ return nullptr;
+ }
+
+ scoped_refptr<VideoFrame> frame(
+ new VideoFrame(*layout, storage, gfx::Rect(size), size, timestamp));
+ frame->buffer_handle_ = handle;
+ return frame;
+}
+
+scoped_refptr<VideoFrame> VideoFrame::WrapTBMInterProcessFrame(
+ scoped_refptr<VideoFrame> frame) {
+ if (frame->format() != PIXEL_FORMAT_TBM_INTER_PROCESS_BUFFER) {
+ DLOG(ERROR) << "Unsupported pixel format: "
+ << VideoPixelFormatToString(frame->format());
+ return nullptr;
+ }
+
+ scoped_refptr<VideoFrame> wrapping_frame(new VideoFrame(
+ frame->layout(), StorageType::STORAGE_TBM_SURFACE, frame->visible_rect(),
+ frame->natural_size(), frame->timestamp()));
+
+ wrapping_frame->metadata().MergeMetadataFrom(frame->metadata());
+ wrapping_frame->wrapped_frame_ = std::move(frame);
+ return wrapping_frame;
+}
#endif
#endif
wrapping_frame->BackWithSharedMemory(frame->shm_region_);
}
-#if defined(TIZEN_TBM_SUPPORT)
- if (frame->format() == PIXEL_FORMAT_TBM_INTER_PROCESS_BUFFER ||
- frame->format() == PIXEL_FORMAT_TBM_SURFACE) {
- wrapping_frame->buffer_handle_ = frame->buffer_handle_;
- }
-#endif
wrapping_frame->wrapped_frame_ = std::move(frame);
return wrapping_frame;
return Columns(plane, format(), coded_size().width());
}
+#if defined(TIZEN_TBM_SUPPORT)
+void VideoFrame::MapTbmMemory(size_t plane) const {
+ const VideoPixelFormat fmt = format();
+ if (PIXEL_FORMAT_TBM_INTER_PROCESS_BUFFER != fmt)
+ return;
+
+ // Calculate an offset that is properly aligned for all planes.
+ const gfx::Size alignment = CommonAlignment(format());
+ const gfx::Point offset(
+ base::bits::AlignDown(visible_rect_.x(), alignment.width()),
+ base::bits::AlignDown(visible_rect_.y(), alignment.height()));
+
+ const gfx::Size subsample = SampleSize(format(), plane);
+ DCHECK(offset.x() % subsample.width() == 0);
+ DCHECK(offset.y() % subsample.height() == 0);
+
+ if (!bufmgr_) {
+ bufmgr_ = tbm_bufmgr_init(-1);
+ }
+ {
+ base::AutoLock autolock(tbm_map_lock_);
+ if (!vp_[plane]) {
+ const auto& buffer_handle = GetTbmBuffer();
+ bo_[plane] = tbm_bo_import(bufmgr_, buffer_handle.key[plane]);
+ bo_handle_[plane] =
+ tbm_bo_map(bo_[plane], TBM_DEVICE_CPU, TBM_OPTION_READ);
+
+ vp_[plane] =
+ (const uint8_t*)bo_handle_[plane].ptr +
+ stride(plane) * (offset.y() / subsample.height()) + // Row offset.
+ BytesPerElement(format(), plane) * // Column offset.
+ (offset.x() / subsample.width());
+ }
+ }
+}
+#endif
+
+const uint8_t* VideoFrame::data(size_t plane) const {
+ DCHECK(IsValidPlane(format(), plane));
+ DCHECK(IsMappable());
+#if defined(TIZEN_TBM_SUPPORT)
+ const VideoPixelFormat fmt = format();
+ if (PIXEL_FORMAT_TBM_INTER_PROCESS_BUFFER == fmt) {
+ if (!vp_[plane]) {
+ MapTbmMemory(plane);
+ }
+ return static_cast<uint8_t*>(bo_handle_[plane].ptr);
+ } else {
+#endif
+ return data_[plane];
+#if defined(TIZEN_TBM_SUPPORT)
+ }
+#endif
+}
+
+uint8_t* VideoFrame::data(size_t plane) {
+ return const_cast<uint8_t*>(
+ static_cast<const VideoFrame*>(this)->data(plane));
+}
+
const uint8_t* VideoFrame::visible_data(size_t plane) const {
DCHECK(IsValidPlane(format(), plane));
DCHECK(IsMappable());
#if defined(TIZEN_TBM_SUPPORT)
const VideoPixelFormat fmt = format();
if (PIXEL_FORMAT_TBM_INTER_PROCESS_BUFFER == fmt) {
- if (!bufmgr_) {
- bufmgr_ = tbm_bufmgr_init(-1);
- }
- {
- base::AutoLock autolock(tbm_map_lock_);
- if (!vp_[plane]) {
- bo_[plane] = tbm_bo_import(bufmgr_, buffer_handle_.key[plane]);
- bo_handle_[plane] =
- tbm_bo_map(bo_[plane], TBM_DEVICE_CPU, TBM_OPTION_READ);
-
- vp_[plane] =
- (const uint8_t*)bo_handle_[plane].ptr +
- stride(plane) * (offset.y() / subsample.height()) + // Row offset.
- BytesPerElement(format(), plane) * // Column offset.
- (offset.x() / subsample.width());
- }
+ if (!vp_[plane]) {
+ MapTbmMemory(plane);
}
return vp_[plane];
}
: mailbox_holders_[texture_index];
}
+void VideoFrame::write_mailbox_holder(size_t texture_index,
+ gpu::MailboxHolder holder) {
+#if defined(TIZEN_TBM_SUPPORT)
+ DCHECK(IsTBMBackend() || HasTextures());
+#else
+ DCHECK(HasTextures());
+#endif
+ DCHECK(IsValidPlane(format(), texture_index));
+ if (wrapped_frame_)
+ wrapped_frame_->write_mailbox_holder(texture_index, holder);
+ else
+ mailbox_holders_[texture_index] = holder;
+}
+
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
const std::vector<base::ScopedFD>& VideoFrame::DmabufFds() const {
DCHECK_EQ(storage_type_, STORAGE_DMABUFS);
#if defined(USE_TTRACE)
TTRACE(TTRACE_TAG_WEB, "VideoFrameCompositor::CreateTbmTextureIfNeeded");
#endif
+
base::AutoLock autolock(tbm_lock_);
- if (!gl || texture_id_ || !buffer_handle_.tbm_surface)
- return (gl_ == gl) ? texture_id_ : 0;
+ auto& tex = GetTbmTexture();
+ auto& gl_ctx = GetGl();
+ if (!gl || tex)
+ return (gl_ctx == gl) ? tex : 0;
- gl_ = gl;
unsigned image = gl->CreateTizenImageCHROMIUM(
- buffer_handle_, visible_rect().width(), visible_rect().height(), GL_RGBA);
- gl->GenTextures(1, &texture_id_);
- gl->BindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
+ GetTbmBuffer(), visible_rect().width(), visible_rect().height(), GL_RGBA);
+ if (!image) {
+ LOG(ERROR) << "CreateTizenImageCHROMIUM failed, tex = " << tex;
+ return false;
+ }
+ auto& img_id = GetImageID();
+ img_id = image;
+ gl_ctx = gl;
+
+ gl->GenTextures(1, &tex);
+ gl->BindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
#if defined(_DEBUG_TBM_VIDEO_RENDERING) && _DEBUG_TBM_VIDEO_RENDERING
LOG(INFO) << "VideoFrame > ++CreateTbmTextureIfNeeded >"
- << ", tbm:" << buffer_handle_.tbm_surface << ", img:" << image
- << ", txt:" << texture_id_;
+ << ", tbm:" << GetTbmBuffer().tbm_surface << ", img:" << image
+ << ", txt:" << tex;
#endif
gpu::Mailbox mailbox;
- gl->ProduceTextureDirectCHROMIUM(texture_id_, mailbox.name);
+ gl->ProduceTextureDirectCHROMIUM(tex, mailbox.name);
gl->ShallowFlushCHROMIUM();
gpu::SyncToken sync_token;
gl->GenSyncTokenCHROMIUM(sync_token.GetData());
- mailbox_holders_[kARGBPlane] =
- gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_EXTERNAL_OES);
+
+ write_mailbox_holder(kARGBPlane, gpu::MailboxHolder(mailbox, sync_token,
+ GL_TEXTURE_EXTERNAL_OES));
SetReleaseMailboxCB(base::BindOnce(ReleaseTbmTexture,
base::ThreadTaskRunnerHandle::Get(), gl,
- texture_id_, image, context_provider_));
- return texture_id_;
+ tex, image, context_provider_));
+ return tex;
}
#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
return false;
}
- if (!buffer_handle_.tbm_surface) {
+ const auto& tbm_buffer_handle = GetTbmBuffer();
+ if (!tbm_buffer_handle.tbm_surface) {
LOG(WARNING) << "No TBM surface registered in video_frame.";
return false;
}
texture_id_ = textureId;
- uint32_t image = gl->CreateTizenImageCHROMIUM(
- buffer_handle_, visible_rect().width(), visible_rect().height(), GL_RGBA);
+ uint32_t image =
+ gl->CreateTizenImageCHROMIUM(tbm_buffer_handle, visible_rect().width(),
+ visible_rect().height(), GL_RGBA);
if (!image) {
LOG(ERROR) << "CreateTizenImageCHROMIUM failed, textureId = " << textureId;
return false;
}
+ auto& img_id = GetImageID();
+ auto& tex_id = GetTbmTexture();
+ img_id = image;
+ tex_id = textureId;
+
gl->BindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
const gfx::Size& size,
base::TimeDelta timestamp,
gfx::TbmBufferHandle handle);
+ static scoped_refptr<VideoFrame> WrapTBMInterProcessBuffer(
+ const gfx::Size& size,
+ base::TimeDelta timestamp,
+ gfx::TbmBufferHandle handle,
+ const StorageType storage);
+ static scoped_refptr<VideoFrame> WrapTBMInterProcessFrame(
+ scoped_refptr<VideoFrame> frame);
#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
bool CreateTbmTextureIfNeeded(gpu::gles2::GLES2Interface* gl,
unsigned textureId);
#endif // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
#endif
+ void MapTbmMemory(size_t plane) const;
// Needed when we have video-frame content in tbm surface.
static scoped_refptr<VideoFrame> WrapTBMSurface(const gfx::Size& size,
base::TimeDelta timestamp,
gfx::TbmBufferHandle handle);
+
+ scoped_refptr<VideoFrame> GetWrapFrame() { return wrapped_frame_; }
+ const VideoFrame* GetWrapFrame() const { return wrapped_frame_.get(); }
bool IsTBMBackend() const { return storage_type_ == STORAGE_TBM_SURFACE; }
- unsigned GetTbmTexture() { return texture_id_; }
+ unsigned& GetTbmTexture() {
+ return wrapped_frame_ ? wrapped_frame_->GetTbmTexture() : texture_id_;
+ }
+ gpu::gles2::GLES2Interface*& GetGl() {
+ return wrapped_frame_ ? wrapped_frame_->GetGl() : gl_;
+ }
unsigned CreateTbmTextureIfNeeded(gpu::gles2::GLES2Interface* gl);
void ReleaseTbm();
void SetTbmTexture(unsigned texture) { texture_id_ = texture; }
- gfx::TbmBufferHandle GetTbmBuffer() { return buffer_handle_; }
- unsigned GetImageID() { return image_id_; }
+ const gfx::TbmBufferHandle& GetTbmBuffer() const {
+ return wrapped_frame_ ? wrapped_frame_->GetTbmBuffer() : buffer_handle_;
+ }
+ unsigned& GetImageID() {
+ return wrapped_frame_ ? wrapped_frame_->GetImageID() : image_id_;
+ }
void SetImageID(unsigned image_id) { image_id_ = image_id; }
void SetContextProvider(
scoped_refptr<viz::ContextProvider> context_provider) {
// Returns pointer to the buffer for a given plane, if this is an
// IsMappable() frame type. The memory is owned by VideoFrame object and must
// not be freed by the caller.
- const uint8_t* data(size_t plane) const {
- DCHECK(IsValidPlane(format(), plane));
- DCHECK(IsMappable());
- return data_[plane];
- }
- uint8_t* data(size_t plane) {
- DCHECK(IsValidPlane(format(), plane));
- DCHECK(IsMappable());
- return data_[plane];
- }
+ const uint8_t* data(size_t plane) const;
+ uint8_t* data(size_t plane);
const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info() const {
return wrapped_frame_ ? wrapped_frame_->ycbcr_info() : ycbcr_info_;
// Only valid to call if this is a NATIVE_TEXTURE frame. Before using the
// mailbox, the caller must wait for the included sync point.
const gpu::MailboxHolder& mailbox_holder(size_t texture_index) const;
+ void write_mailbox_holder(size_t texture_index, gpu::MailboxHolder holder);
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
// Returns a vector containing the backing DmaBufs for this frame. The number