1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-04-08 16:54:03 +02:00

kmsgrab: Refactor and clean error cases

This commit is contained in:
Mark Thompson 2020-07-05 16:49:43 +01:00
parent ea8f8d28d0
commit fa0b064cf2

View File

@ -81,70 +81,44 @@ static void kmsgrab_free_frame(void *opaque, uint8_t *data)
av_frame_free(&frame);
}
static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt)
static int kmsgrab_get_fb(AVFormatContext *avctx,
drmModePlane *plane,
AVDRMFrameDescriptor *desc)
{
KMSGrabContext *ctx = avctx->priv_data;
drmModePlane *plane;
drmModeFB *fb;
AVDRMFrameDescriptor *desc;
AVFrame *frame;
int64_t now;
drmModeFB *fb = NULL;
int err, fd;
now = av_gettime();
if (ctx->frame_last) {
int64_t delay;
while (1) {
delay = ctx->frame_last + ctx->frame_delay - now;
if (delay <= 0)
break;
av_usleep(delay);
now = av_gettime();
}
}
ctx->frame_last = now;
plane = drmModeGetPlane(ctx->hwctx->fd, ctx->plane_id);
if (!plane) {
av_log(avctx, AV_LOG_ERROR, "Failed to get plane "
"%"PRIu32".\n", ctx->plane_id);
return AVERROR(EIO);
}
if (!plane->fb_id) {
av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" no longer has "
"an associated framebuffer.\n", ctx->plane_id);
return AVERROR(EIO);
}
fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id);
if (!fb) {
err = errno;
av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer "
"%"PRIu32".\n", plane->fb_id);
return AVERROR(EIO);
"%"PRIu32": %s.\n", plane->fb_id, strerror(err));
err = AVERROR(err);
goto fail;
}
if (fb->width != ctx->width || fb->height != ctx->height) {
av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
"dimensions changed: now %"PRIu32"x%"PRIu32".\n",
ctx->plane_id, fb->width, fb->height);
return AVERROR(EIO);
err = AVERROR(EIO);
goto fail;
}
if (!fb->handle) {
av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n");
return AVERROR(EIO);
err = AVERROR(EIO);
goto fail;
}
err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handle, O_RDONLY, &fd);
if (err < 0) {
err = errno;
av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from "
"framebuffer handle: %s.\n", strerror(errno));
return AVERROR(err);
"framebuffer handle: %s.\n", strerror(err));
err = AVERROR(err);
goto fail;
}
desc = av_mallocz(sizeof(*desc));
if (!desc)
return AVERROR(ENOMEM);
*desc = (AVDRMFrameDescriptor) {
.nb_objects = 1,
.objects[0] = {
@ -164,31 +138,93 @@ static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt)
},
};
err = 0;
fail:
drmModeFreeFB(fb);
return err;
}
static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt)
{
KMSGrabContext *ctx = avctx->priv_data;
drmModePlane *plane = NULL;
AVDRMFrameDescriptor *desc = NULL;
AVFrame *frame = NULL;
int64_t now;
int err;
now = av_gettime();
if (ctx->frame_last) {
int64_t delay;
while (1) {
delay = ctx->frame_last + ctx->frame_delay - now;
if (delay <= 0)
break;
av_usleep(delay);
now = av_gettime();
}
}
ctx->frame_last = now;
plane = drmModeGetPlane(ctx->hwctx->fd, ctx->plane_id);
if (!plane) {
err = errno;
av_log(avctx, AV_LOG_ERROR, "Failed to get plane "
"%"PRIu32": %s.\n", ctx->plane_id, strerror(err));
err = AVERROR(err);
goto fail;
}
if (!plane->fb_id) {
av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" no longer has "
"an associated framebuffer.\n", ctx->plane_id);
err = AVERROR(EIO);
goto fail;
}
desc = av_mallocz(sizeof(*desc));
if (!desc) {
err = AVERROR(ENOMEM);
goto fail;
}
err = kmsgrab_get_fb(avctx, plane, desc);
if (err < 0)
goto fail;
frame = av_frame_alloc();
if (!frame)
return AVERROR(ENOMEM);
if (!frame) {
err = AVERROR(ENOMEM);
goto fail;
}
frame->hw_frames_ctx = av_buffer_ref(ctx->frames_ref);
if (!frame->hw_frames_ctx)
return AVERROR(ENOMEM);
if (!frame->hw_frames_ctx) {
err = AVERROR(ENOMEM);
goto fail;
}
frame->buf[0] = av_buffer_create((uint8_t*)desc, sizeof(*desc),
&kmsgrab_free_desc, avctx, 0);
if (!frame->buf[0])
return AVERROR(ENOMEM);
if (!frame->buf[0]) {
err = AVERROR(ENOMEM);
goto fail;
}
frame->data[0] = (uint8_t*)desc;
frame->format = AV_PIX_FMT_DRM_PRIME;
frame->width = fb->width;
frame->height = fb->height;
frame->width = ctx->width;
frame->height = ctx->height;
drmModeFreeFB(fb);
drmModeFreePlane(plane);
plane = NULL;
desc = NULL;
pkt->buf = av_buffer_create((uint8_t*)frame, sizeof(*frame),
&kmsgrab_free_frame, avctx, 0);
if (!pkt->buf)
return AVERROR(ENOMEM);
if (!pkt->buf) {
err = AVERROR(ENOMEM);
goto fail;
}
pkt->data = (uint8_t*)frame;
pkt->size = sizeof(*frame);
@ -196,6 +232,12 @@ static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt)
pkt->flags |= AV_PKT_FLAG_TRUSTED;
return 0;
fail:
drmModeFreePlane(plane);
av_freep(&desc);
av_frame_free(&frame);
return err;
}
static const struct {
@ -289,9 +331,10 @@ static av_cold int kmsgrab_read_header(AVFormatContext *avctx)
} else {
plane_res = drmModeGetPlaneResources(ctx->hwctx->fd);
if (!plane_res) {
err = errno;
av_log(avctx, AV_LOG_ERROR, "Failed to get plane "
"resources: %s.\n", strerror(errno));
err = AVERROR(EINVAL);
"resources: %s.\n", strerror(err));
err = AVERROR(err);
goto fail;
}
@ -402,13 +445,9 @@ static av_cold int kmsgrab_read_header(AVFormatContext *avctx)
err = 0;
fail:
if (plane_res)
drmModeFreePlaneResources(plane_res);
if (plane)
drmModeFreePlane(plane);
if (fb)
drmModeFreeFB(fb);
drmModeFreePlaneResources(plane_res);
drmModeFreePlane(plane);
drmModeFreeFB(fb);
return err;
}