diff --git a/libobs/media-io/video-frame.c b/libobs/media-io/video-frame.c index 81f95234a..d950814ba 100644 --- a/libobs/media-io/video-frame.c +++ b/libobs/media-io/video-frame.c @@ -83,6 +83,17 @@ void video_frame_init(struct video_frame *frame, enum video_format format, frame->data[0] = bmalloc(size); frame->linesize[0] = width*4; break; + + case VIDEO_FORMAT_I444: + size = width * height; + ALIGN_SIZE(size, alignment); + frame->data[0] = bmalloc(size * 3); + frame->data[1] = (uint8_t*)frame->data[0] + size; + frame->data[2] = (uint8_t*)frame->data[1] + size; + frame->linesize[0] = width; + frame->linesize[1] = width; + frame->linesize[2] = width; + break; } } @@ -112,5 +123,11 @@ void video_frame_copy(struct video_frame *dst, const struct video_frame *src, case VIDEO_FORMAT_BGRX: memcpy(dst->data[0], src->data[0], src->linesize[0] * cy); break; + + case VIDEO_FORMAT_I444: + memcpy(dst->data[0], src->data[0], src->linesize[0] * cy); + memcpy(dst->data[1], src->data[1], src->linesize[1] * cy); + memcpy(dst->data[2], src->data[2], src->linesize[2] * cy); + break; } } diff --git a/libobs/media-io/video-io.h b/libobs/media-io/video-io.h index 04ca64b7d..7fae63c10 100644 --- a/libobs/media-io/video-io.h +++ b/libobs/media-io/video-io.h @@ -46,6 +46,9 @@ enum video_format { VIDEO_FORMAT_RGBA, VIDEO_FORMAT_BGRA, VIDEO_FORMAT_BGRX, + + /* planar 4:4:4 */ + VIDEO_FORMAT_I444, }; enum video_colorspace { @@ -88,6 +91,7 @@ static inline bool format_is_yuv(enum video_format format) case VIDEO_FORMAT_YVYU: case VIDEO_FORMAT_YUY2: case VIDEO_FORMAT_UYVY: + case VIDEO_FORMAT_I444: return true; case VIDEO_FORMAT_NONE: case VIDEO_FORMAT_RGBA: diff --git a/libobs/media-io/video-scaler-ffmpeg.c b/libobs/media-io/video-scaler-ffmpeg.c index 883fab264..31f721e33 100644 --- a/libobs/media-io/video-scaler-ffmpeg.c +++ b/libobs/media-io/video-scaler-ffmpeg.c @@ -38,6 +38,7 @@ static inline enum AVPixelFormat get_ffmpeg_video_format( case VIDEO_FORMAT_RGBA: return AV_PIX_FMT_RGBA; case VIDEO_FORMAT_BGRA: return AV_PIX_FMT_BGRA; case VIDEO_FORMAT_BGRX: return AV_PIX_FMT_BGRA; + case VIDEO_FORMAT_I444: return AV_PIX_FMT_YUV444P; } return AV_PIX_FMT_NONE; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 1df51e76d..eaf3604c7 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -791,6 +791,7 @@ static inline enum convert_type get_convert_type(enum video_format format) case VIDEO_FORMAT_UYVY: return CONVERT_422_U; + case VIDEO_FORMAT_I444: case VIDEO_FORMAT_NONE: case VIDEO_FORMAT_RGBA: case VIDEO_FORMAT_BGRA: @@ -963,6 +964,7 @@ static const char *select_conversion_technique(enum video_format format) case VIDEO_FORMAT_BGRX: case VIDEO_FORMAT_RGBA: case VIDEO_FORMAT_NONE: + case VIDEO_FORMAT_I444: assert(false && "No conversion requested"); break; } @@ -1598,6 +1600,12 @@ static void copy_frame_data(struct obs_source_frame *dst, copy_frame_data_plane(dst, src, 1, dst->height/2); break; + case VIDEO_FORMAT_I444: + copy_frame_data_plane(dst, src, 0, dst->height); + copy_frame_data_plane(dst, src, 1, dst->height); + copy_frame_data_plane(dst, src, 2, dst->height); + break; + case VIDEO_FORMAT_YVYU: case VIDEO_FORMAT_YUY2: case VIDEO_FORMAT_UYVY: diff --git a/libobs/obs-video.c b/libobs/obs-video.c index 3c8b323ca..f661bb817 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -457,6 +457,12 @@ static void convert_frame( 0, info->height, output->data, output->linesize); + } else if (info->format == VIDEO_FORMAT_I444) { + convert_uyvx_to_i444( + input->data[0], input->linesize[0], + 0, info->height, + output->data, output->linesize); + } else { blog(LOG_ERROR, "convert_frame: unsupported texture format"); } diff --git a/libobs/obs.c b/libobs/obs.c index cfaf606c9..7e128b14b 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -118,6 +118,37 @@ static inline void set_nv12_sizes(const struct obs_video_info *ovi) video->conversion_tech = "NV12"; } +static inline void set_444p_sizes(const struct obs_video_info *ovi) +{ + struct obs_core_video *video = &obs->video; + uint32_t chroma_pixels; + uint32_t total_bytes; + + chroma_pixels = (ovi->output_width * ovi->output_height); + chroma_pixels = GET_ALIGN(chroma_pixels, PIXEL_SIZE); + + video->plane_offsets[0] = 0; + video->plane_offsets[1] = chroma_pixels; + video->plane_offsets[2] = chroma_pixels + chroma_pixels; + + video->plane_linewidth[0] = ovi->output_width; + video->plane_linewidth[1] = ovi->output_width; + video->plane_linewidth[2] = ovi->output_width; + + video->plane_sizes[0] = chroma_pixels; + video->plane_sizes[1] = chroma_pixels; + video->plane_sizes[2] = chroma_pixels; + + total_bytes = video->plane_offsets[2] + chroma_pixels; + + video->conversion_height = + (total_bytes/PIXEL_SIZE + ovi->output_width-1) / + ovi->output_width; + + video->conversion_height = GET_ALIGN(video->conversion_height, 2); + video->conversion_tech = "Planar444"; +} + static inline void calc_gpu_conversion_sizes(const struct obs_video_info *ovi) { obs->video.conversion_height = 0; @@ -133,6 +164,9 @@ static inline void calc_gpu_conversion_sizes(const struct obs_video_info *ovi) case VIDEO_FORMAT_NV12: set_nv12_sizes(ovi); break; + case VIDEO_FORMAT_I444: + set_444p_sizes(ovi); + break; } } diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-formats.h b/plugins/obs-ffmpeg/obs-ffmpeg-formats.h index ad3918e4f..7b70e6e60 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-formats.h +++ b/plugins/obs-ffmpeg/obs-ffmpeg-formats.h @@ -12,6 +12,7 @@ static inline enum AVPixelFormat obs_to_ffmpeg_video_format( { switch (format) { case VIDEO_FORMAT_NONE: return AV_PIX_FMT_NONE; + case VIDEO_FORMAT_I444: return AV_PIX_FMT_YUV444P; case VIDEO_FORMAT_I420: return AV_PIX_FMT_YUV420P; case VIDEO_FORMAT_NV12: return AV_PIX_FMT_NV12; case VIDEO_FORMAT_YVYU: return AV_PIX_FMT_NONE; @@ -29,6 +30,7 @@ static inline enum video_format ffmpeg_to_obs_video_format( enum AVPixelFormat format) { switch (format) { + case AV_PIX_FMT_YUV444P: return VIDEO_FORMAT_I444; case AV_PIX_FMT_YUV420P: return VIDEO_FORMAT_I420; case AV_PIX_FMT_NV12: return VIDEO_FORMAT_NV12; case AV_PIX_FMT_YUYV422: return VIDEO_FORMAT_YUY2;