You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
3.1 KiB
96 lines
3.1 KiB
/*****************************************************************************
|
|
* V210.cpp: V210 picture conversion
|
|
*****************************************************************************
|
|
* Copyright © 2014-2016 VideoLAN and VideoLAN Authors
|
|
* 2018 VideoLabs
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser 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.
|
|
*****************************************************************************/
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include "V210.hpp"
|
|
|
|
#include <vlc_picture.h>
|
|
|
|
using namespace sdi;
|
|
|
|
static inline unsigned clip(unsigned a)
|
|
{
|
|
if (a < 4) return 4;
|
|
else if (a > 1019) return 1019;
|
|
else return a;
|
|
}
|
|
|
|
static inline void put_le32(uint8_t **p, uint32_t d)
|
|
{
|
|
SetDWLE(*p, d);
|
|
(*p) += 4;
|
|
}
|
|
|
|
void V210::Convert(const picture_t *pic, unsigned dst_stride, void *frame_bytes)
|
|
{
|
|
unsigned width = pic->format.i_width;
|
|
unsigned height = pic->format.i_height;
|
|
unsigned payload_size = ((width * 8 + 11) / 12) * 4;
|
|
unsigned line_padding = (payload_size < dst_stride) ? dst_stride - payload_size : 0;
|
|
unsigned h, w;
|
|
uint8_t *dst = (uint8_t*)frame_bytes;
|
|
|
|
const uint16_t *y = (const uint16_t*)pic->p[0].p_pixels;
|
|
const uint16_t *u = (const uint16_t*)pic->p[1].p_pixels;
|
|
const uint16_t *v = (const uint16_t*)pic->p[2].p_pixels;
|
|
|
|
#define WRITE_PIXELS(a, b, c) \
|
|
do { \
|
|
val = clip(*a++); \
|
|
val |= (clip(*b++) << 10) | \
|
|
(clip(*c++) << 20); \
|
|
put_le32(&dst, val); \
|
|
} while (0)
|
|
|
|
for (h = 0; h < height; h++) {
|
|
uint32_t val = 0;
|
|
for (w = 0; w + 5 < width; w += 6) {
|
|
WRITE_PIXELS(u, y, v);
|
|
WRITE_PIXELS(y, u, y);
|
|
WRITE_PIXELS(v, y, u);
|
|
WRITE_PIXELS(y, v, y);
|
|
}
|
|
if (w + 1 < width) {
|
|
WRITE_PIXELS(u, y, v);
|
|
|
|
val = clip(*y++);
|
|
if (w + 2 == width)
|
|
put_le32(&dst, val);
|
|
#undef WRITE_PIXELS
|
|
}
|
|
if (w + 3 < width) {
|
|
val |= (clip(*u++) << 10) | (clip(*y++) << 20);
|
|
put_le32(&dst, val);
|
|
|
|
val = clip(*v++) | (clip(*y++) << 10);
|
|
put_le32(&dst, val);
|
|
}
|
|
|
|
memset(dst, 0, line_padding);
|
|
dst += line_padding;
|
|
|
|
y += pic->p[0].i_pitch / 2 - width;
|
|
u += pic->p[1].i_pitch / 2 - width / 2;
|
|
v += pic->p[2].i_pitch / 2 - width / 2;
|
|
}
|
|
}
|
|
|