Select Git revision
media_buffer.cpp
-
Philippe Gorley authored
FFmpeg's av_image_fill_black supports more pixel formats. Works around casting int* to ptrdiff_t* on platforms where ptrdiff_t is not the same size as int by recreating the linesize array. Change-Id: I2825b18c6acc921a3cd3bb1398565df0aa657153
Philippe Gorley authoredFFmpeg's av_image_fill_black supports more pixel formats. Works around casting int* to ptrdiff_t* on platforms where ptrdiff_t is not the same size as int by recreating the linesize array. Change-Id: I2825b18c6acc921a3cd3bb1398565df0aa657153
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
media_buffer.cpp 4.26 KiB
/*
* Copyright (C) 2015-2018 Savoir-faire Linux Inc.
*
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "libav_deps.h" // MUST BE INCLUDED FIRST
#include "libav_utils.h"
#include "media_buffer.h"
#include "dring/videomanager_interface.h"
#include <new> // std::bad_alloc
#include <cstdlib>
#include <cstring> // std::memset
#include <ciso646> // fix windows compiler bug
namespace ring {
MediaFrame::MediaFrame()
: frame_ {av_frame_alloc(), [](AVFrame* frame){ av_frame_free(&frame); }}
{
if (not frame_)
throw std::bad_alloc();
}
void
MediaFrame::reset() noexcept
{
av_frame_unref(frame_.get());
}
#ifdef RING_VIDEO
VideoFrame::~VideoFrame()
{
if (releaseBufferCb_)
releaseBufferCb_(ptr_);
}
void
VideoFrame::reset() noexcept
{
MediaFrame::reset();
#if !USE_OLD_AVU
allocated_ = false;
#endif
releaseBufferCb_ = {};
}
size_t
VideoFrame::size() const noexcept
{
return videoFrameSize(format(), width(), height());
}
int
VideoFrame::format() const noexcept
{
return libav_utils::ring_pixel_format(frame_->format);
}
int
VideoFrame::width() const noexcept
{
return frame_->width;
}
int
VideoFrame::height() const noexcept
{
return frame_->height;
}
void
VideoFrame::setGeometry(int format, int width, int height) noexcept
{
frame_->format = libav_utils::libav_pixel_format(format);
frame_->width = width;
frame_->height = height;
}
void
VideoFrame::reserve(int format, int width, int height)
{
auto libav_format = (AVPixelFormat)libav_utils::libav_pixel_format(format);
auto libav_frame = frame_.get();
if (allocated_) {
// nothing to do if same properties
if (width == libav_frame->width
and height == libav_frame->height
and libav_format == libav_frame->format)
#if USE_OLD_AVU
avpicture_free((AVPicture *) libav_frame);
#else
av_frame_unref(libav_frame);
#endif
}
setGeometry(format, width, height);
if (av_frame_get_buffer(libav_frame, 32))
throw std::bad_alloc();
allocated_ = true;
releaseBufferCb_ = {};
}
void
VideoFrame::setFromMemory(uint8_t* ptr, int format, int width, int height) noexcept
{
reset();
setGeometry(format, width, height);
if (not ptr)
return;
av_image_fill_arrays(frame_->data, frame_->linesize, (uint8_t*)ptr,
(AVPixelFormat)frame_->format, width, height, 1);
}
void
VideoFrame::setFromMemory(uint8_t* ptr, int format, int width, int height,
std::function<void(uint8_t*)> cb) noexcept
{
setFromMemory(ptr, format, width, height);
if (cb) {
releaseBufferCb_ = cb;
ptr_ = ptr;
}
}
void
VideoFrame::noise()
{
auto f = frame_.get();
if (f->data[0] == nullptr)
return;
for (std::size_t i=0 ; i < size(); ++i) {
f->data[0][i] = std::rand() & 255;
}
}
VideoFrame&
VideoFrame::operator =(const VideoFrame& src)
{
reserve(src.format(), src.width(), src.height());
auto source = src.pointer();
av_image_copy(frame_->data, frame_->linesize, (const uint8_t **)source->data,
source->linesize, (AVPixelFormat)frame_->format,
frame_->width, frame_->height);
return *this;
}
//=== HELPERS ==================================================================
std::size_t
videoFrameSize(int format, int width, int height)
{
return av_image_get_buffer_size((AVPixelFormat)libav_utils::libav_pixel_format(format),
width, height, 1);
}
#endif // RING_VIDEO
} // namespace ring