linuxOS_AP05/buildroot/package/ffmpeg/0002-ffplay-support-display-buffer-with-drm-format.patch

223 lines
8.5 KiB
Diff
Raw Normal View History

2025-06-02 05:59:07 +00:00
From 1e68556c2a834bfd584070adee1aa981d8780b9a Mon Sep 17 00:00:00 2001
From: Hertz Wang <wangh@rock-chips.com>
Date: Mon, 29 Oct 2018 11:58:31 +0800
Subject: [PATCH 02/11] ffplay support display buffer with drm format
This patch disable the video filter to support display drm buffer.
If need video filter, we should duplicate a intermediate frame.
Change-Id: Ic50932841c5f86e928a0c0838844eaadb4d138c0
Signed-off-by: Hertz Wang <wangh@rock-chips.com>
---
fftools/ffplay.c | 76 +++++++++++++++++++++++++++++++++++++++++++----
libavcodec/rkmppdec.c | 1 +
libavutil/hwcontext_drm.h | 6 ++++
3 files changed, 77 insertions(+), 6 deletions(-)
diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index ab1f9fa..a0be207 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -28,6 +28,7 @@
#include <math.h>
#include <limits.h>
#include <signal.h>
+#include <stdbool.h>
#include <stdint.h>
#include "libavutil/avstring.h"
@@ -60,6 +61,9 @@
#include <assert.h>
+#include <drm_fourcc.h>
+#include "libavutil/hwcontext_drm.h"
+
const char program_name[] = "ffplay";
const int program_birth_year = 2003;
@@ -906,10 +910,46 @@ static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_B
}
}
+static void get_avframe_info(AVFrame *frame,
+ uint8_t *srcSlice[],
+ int srcStride[]) {
+ if (frame->format != AV_PIX_FMT_DRM_PRIME) {
+ memcpy(srcSlice, frame->data, sizeof(frame->data));
+ memcpy(srcStride, frame->linesize, sizeof(frame->linesize));
+ } else {
+ AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)frame->data[0];
+ AVDRMLayerDescriptor *layer = &desc->layers[0];
+ memset(srcSlice, 0, sizeof(frame->data));
+ memset(srcStride, 0, sizeof(frame->linesize));
+ srcSlice[0] = (uint8_t*)desc->objects[0].ptr;
+ srcSlice[1] = srcSlice[0] + layer->planes[1].offset;
+ srcStride[0] = srcStride[1] = layer->planes[0].pitch;
+ }
+}
+
+static int get_avframe_format(AVFrame *frame) {
+ int av_format = frame->format;
+ if (av_format == AV_PIX_FMT_DRM_PRIME) {
+ AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)frame->data[0];
+ AVDRMLayerDescriptor *layer = &desc->layers[0];
+ switch (layer->format) {
+ case DRM_FORMAT_NV12: return AV_PIX_FMT_NV12;
+#ifdef DRM_FORMAT_NV12_10
+ case DRM_FORMAT_NV12_10: return AV_PIX_FMT_P010LE;
+#endif
+ default:
+ av_log(NULL, AV_LOG_FATAL, "Unknown DRM Format: %d\n",
+ layer->format);
+ }
+ }
+ return av_format;
+}
+
static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext **img_convert_ctx) {
int ret = 0;
Uint32 sdl_pix_fmt;
SDL_BlendMode sdl_blendmode;
+ int av_format = get_avframe_format(frame);
get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode);
if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0)
return -1;
@@ -917,13 +957,17 @@ static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext *
case SDL_PIXELFORMAT_UNKNOWN:
/* This should only happen if we are not using avfilter... */
*img_convert_ctx = sws_getCachedContext(*img_convert_ctx,
- frame->width, frame->height, frame->format, frame->width, frame->height,
+ frame->width, frame->height, av_format, frame->width, frame->height,
AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL);
if (*img_convert_ctx != NULL) {
uint8_t *pixels[4];
int pitch[4];
if (!SDL_LockTexture(*tex, NULL, (void **)pixels, pitch)) {
- sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize,
+ uint8_t *srcSlice[AV_NUM_DATA_POINTERS] = { NULL };
+ int srcStride[AV_NUM_DATA_POINTERS] = { 0 };
+
+ get_avframe_info(frame, srcSlice, srcStride);
+ sws_scale(*img_convert_ctx, (const uint8_t * const *)srcSlice, srcStride,
0, frame->height, pixels, pitch);
SDL_UnlockTexture(*tex);
}
@@ -2152,6 +2196,9 @@ static int video_thread(void *arg)
}
for (;;) {
+#if CONFIG_AVFILTER
+ bool support_avfilter;
+#endif
ret = get_video_frame(is, frame);
if (ret < 0)
goto the_end;
@@ -2159,11 +2206,16 @@ static int video_thread(void *arg)
continue;
#if CONFIG_AVFILTER
- if ( last_w != frame->width
+ // ffmpeg avfilter do not support drm fmt.
+ // As avfilter will modify pixels, duplicate a intermediate frame
+ // if wanna support avfilter for drm fmt.
+ support_avfilter = (frame->format != AV_PIX_FMT_DRM_PRIME);
+ if (support_avfilter
+ && (last_w != frame->width
|| last_h != frame->height
|| last_format != frame->format
|| last_serial != is->viddec.pkt_serial
- || last_vfilter_idx != is->vfilter_idx) {
+ || last_vfilter_idx != is->vfilter_idx)) {
av_log(NULL, AV_LOG_DEBUG,
"Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
last_w, last_h,
@@ -2189,11 +2241,14 @@ static int video_thread(void *arg)
frame_rate = av_buffersink_get_frame_rate(filt_out);
}
+ if (support_avfilter) {
ret = av_buffersrc_add_frame(filt_in, frame);
if (ret < 0)
goto the_end;
+ }
while (ret >= 0) {
+ if (support_avfilter) {
is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
@@ -2208,13 +2263,14 @@ static int video_thread(void *arg)
if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
is->frame_last_filter_delay = 0;
tb = av_buffersink_get_time_base(filt_out);
+ }
#endif
duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial);
av_frame_unref(frame);
#if CONFIG_AVFILTER
- if (is->videoq.serial != is->viddec.pkt_serial)
+ if (!support_avfilter || is->videoq.serial != is->viddec.pkt_serial)
break;
}
#endif
@@ -2241,8 +2297,11 @@ static int subtitle_thread(void *arg)
if (!(sp = frame_queue_peek_writable(&is->subpq)))
return 0;
- if ((got_subtitle = decoder_decode_frame(&is->subdec, NULL, &sp->sub)) < 0)
+ if ((got_subtitle = decoder_decode_frame(&is->subdec, NULL, &sp->sub)) < 0) {
+ av_log(NULL, AV_LOG_WARNING,
+ "ffplay decode subtitle failed or finished\n");
break;
+ }
pts = 0;
@@ -2258,6 +2317,11 @@ static int subtitle_thread(void *arg)
/* now we can update the picture count */
frame_queue_push(&is->subpq);
} else if (got_subtitle) {
+ if (arg) {
+ av_log(NULL, AV_LOG_WARNING,
+ "ffplay only support graphics subtitle\n");
+ arg = NULL;
+ }
avsubtitle_free(&sp->sub);
}
}
diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index 143d05b..b44861c 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -421,6 +421,7 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame)
desc->nb_objects = 1;
desc->objects[0].fd = mpp_buffer_get_fd(buffer);
+ desc->objects[0].ptr = mpp_buffer_get_ptr(buffer);
desc->objects[0].size = mpp_buffer_get_size(buffer);
desc->nb_layers = 1;
diff --git a/libavutil/hwcontext_drm.h b/libavutil/hwcontext_drm.h
index 42709f2..4c40d15 100644
--- a/libavutil/hwcontext_drm.h
+++ b/libavutil/hwcontext_drm.h
@@ -50,6 +50,12 @@ typedef struct AVDRMObjectDescriptor {
* DRM PRIME fd for the object.
*/
int fd;
+
+ /**
+ * DRM PRIME mapped virtual ptr for above fd.
+ */
+ void *ptr;
+
/**
* Total size of the object.
*
--
2.7.4