mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
video: replace yuv422_clear_to_black
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
This commit is contained in:
@ -226,4 +226,21 @@ getDictValue(const AVDictionary* d, const std::string& key, int flags)
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
fillWithBlack(AVFrame* frame)
|
||||
{
|
||||
const AVPixelFormat format = static_cast<AVPixelFormat>(frame->format);
|
||||
const int planes = av_pix_fmt_count_planes(format);
|
||||
// workaround for casting pointers to different sizes
|
||||
// on 64 bit machines: sizeof(ptrdiff_t) != sizeof(int)
|
||||
ptrdiff_t linesizes[4];
|
||||
for (int i = 0; i < planes; ++i)
|
||||
linesizes[i] = frame->linesize[i];
|
||||
int ret = av_image_fill_black(frame->data, linesizes, format,
|
||||
frame->color_range, frame->width, frame->height);
|
||||
if (ret < 0) {
|
||||
RING_ERR() << "Failed to blacken frame";
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace ring::libav_utils
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <string>
|
||||
|
||||
struct AVDictionary;
|
||||
struct AVFrame;
|
||||
struct AVPixFmtDescriptor;
|
||||
|
||||
namespace ring { namespace libav_utils {
|
||||
@ -47,4 +48,6 @@ namespace ring { namespace libav_utils {
|
||||
|
||||
const char* getDictValue(const AVDictionary* d, const std::string& key, int flags=0);
|
||||
|
||||
void fillWithBlack(AVFrame* frame);
|
||||
|
||||
}} // namespace ring::libav_utils
|
||||
|
@ -171,66 +171,6 @@ videoFrameSize(int format, int width, int height)
|
||||
width, height, 1);
|
||||
}
|
||||
|
||||
void
|
||||
yuv422_clear_to_black(VideoFrame& frame)
|
||||
{
|
||||
const auto libav_frame = frame.pointer();
|
||||
const auto desc = av_pix_fmt_desc_get((AVPixelFormat)libav_frame->format);
|
||||
if (not desc)
|
||||
return;
|
||||
|
||||
if (not libav_utils::is_yuv_planar(*desc)) {
|
||||
// not planar
|
||||
auto stride = libav_frame->linesize[0];
|
||||
if (libav_frame->width % 2) {
|
||||
// non-even width (16bits write x-loop)
|
||||
for (int y = 0; y < libav_frame->height; ++y) {
|
||||
auto src = &libav_frame->data[0][y * stride];
|
||||
for (int x = 0; x < libav_frame->width; ++x) {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
*((uint16_t*)src) = 0x8000;
|
||||
#else
|
||||
*((uint16_t*)src) = 0x0080;
|
||||
#endif
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
} else if (libav_frame->width % 4) {
|
||||
// non-quad width (32bits write x-loop)
|
||||
for (int y = 0; y < libav_frame->height; ++y) {
|
||||
auto src = &libav_frame->data[0][y * stride];
|
||||
for (int x = 0; x < libav_frame->width / 2; ++x) {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
*((uint32_t*)src) = 0x80008000;
|
||||
#else
|
||||
*((uint32_t*)src) = 0x00800080;
|
||||
#endif
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// quad width (64bits write x-loop)
|
||||
for (int y = 0; y < libav_frame->height; ++y) {
|
||||
auto src = &libav_frame->data[0][y * stride];
|
||||
for (int x = 0; x < libav_frame->width / 4; ++x) {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
*((uint64_t*)src) = 0x8000800080008000;
|
||||
#else
|
||||
*((uint64_t*)src) = 0x0080008000800080;
|
||||
#endif
|
||||
src += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// planar
|
||||
std::memset(libav_frame->data[0], 0, libav_frame->linesize[0] * libav_frame->height);
|
||||
// 128 is the black level for U/V channels
|
||||
std::memset(libav_frame->data[1], 128, libav_frame->linesize[1] * (libav_frame->height >> desc->log2_chroma_w));
|
||||
std::memset(libav_frame->data[2], 128, libav_frame->linesize[2] * (libav_frame->height >> desc->log2_chroma_h));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RING_VIDEO
|
||||
|
||||
} // namespace ring
|
||||
|
@ -97,7 +97,6 @@ class VideoFrame: public MediaFrame {
|
||||
|
||||
// Some helpers
|
||||
std::size_t videoFrameSize(int format, int width, int height);
|
||||
void yuv422_clear_to_black(VideoFrame& frame);
|
||||
|
||||
#endif // RING_VIDEO
|
||||
|
||||
|
@ -358,7 +358,7 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
|
||||
/* Prepare a frame suitable to our encoder frame format,
|
||||
* keeping also the input aspect ratio.
|
||||
*/
|
||||
yuv422_clear_to_black(scaledFrame_); // to fill blank space left by the "keep aspect"
|
||||
libav_utils::fillWithBlack(scaledFrame_.pointer());
|
||||
|
||||
scaler_.scale_with_aspect(input, scaledFrame_);
|
||||
|
||||
|
@ -136,7 +136,7 @@ VideoMixer::process()
|
||||
return;
|
||||
}
|
||||
|
||||
yuv422_clear_to_black(output);
|
||||
libav_utils::fillWithBlack(output.pointer());
|
||||
|
||||
{
|
||||
auto lock(rwMutex_.read());
|
||||
@ -190,7 +190,7 @@ VideoMixer::setDimensions(int width, int height)
|
||||
// cleanup the previous frame to have a nice copy in rendering method
|
||||
std::shared_ptr<VideoFrame> previous_p(obtainLastFrame());
|
||||
if (previous_p)
|
||||
yuv422_clear_to_black(*previous_p);
|
||||
libav_utils::fillWithBlack(previous_p->pointer());
|
||||
|
||||
start_sink();
|
||||
}
|
||||
|
Reference in New Issue
Block a user