~emersion/vaapi-decoder

bc7f7b09cbb2918ecb80e3de968e0d2bf4d46b17 — Simon Ser 9 months ago 5d2a7b7
Add helper to get the DRM format of a frame
2 files changed, 42 insertions(+), 3 deletions(-)

M Makefile
M main.c
M Makefile => Makefile +4 -3
@@ 1,11 1,12 @@
CFLAGS = -g -Wall -Wextra -Wno-unused-parameter
avdeps = libavcodec libavformat libavutil
avflags = $(shell pkg-config $(avdeps) --cflags --libs)

deps = libavcodec libavformat libavutil libdrm
depflags = $(shell pkg-config $(deps) --cflags --libs)

all: vaapi-decoder

vaapi-decoder: main.c
	$(CC) $(CFLAGS) $(avflags) -o $@ $^
	$(CC) $(CFLAGS) $(depflags) -o $@ $^

clean:
	$(RM) vaapi-decoder

M main.c => main.c +38 -0
@@ 1,6 1,8 @@
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>

#include <drm_fourcc.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/hwcontext.h>


@@ 9,6 11,33 @@

static enum AVPixelFormat hw_pix_fmt = AV_PIX_FMT_NONE;

static const struct {
	uint32_t format;
	int nb_layers;
	uint32_t layers[AV_DRM_MAX_PLANES];
} drm_format_map[] = {
	{ DRM_FORMAT_NV12, 2, { DRM_FORMAT_R8, DRM_FORMAT_GR88 } },
};

static uint32_t get_drm_frame_format(const AVDRMFrameDescriptor *drm_frame_desc) {
	if (drm_frame_desc->nb_layers == 1) {
		return drm_frame_desc->layers[0].format;
	}
	for (size_t i = 0; i < sizeof(drm_format_map) / sizeof(drm_format_map[0]); i++) {
		if (drm_format_map[i].nb_layers != drm_frame_desc->nb_layers) {
			continue;
		}
		bool match = true;
		for (int j = 0; j < drm_frame_desc->nb_layers; j++) {
			match &= drm_frame_desc->layers[j].format == drm_format_map[i].layers[j];
		}
		if (match) {
			return drm_format_map[i].format;
		}
	}
	return DRM_FORMAT_INVALID;
}

static int check_hw_device_type(enum AVHWDeviceType type) {
	enum AVHWDeviceType t = AV_HWDEVICE_TYPE_NONE;
	while (1) {


@@ 206,6 235,15 @@ int main(int argc, char *argv[]) {
		}
	}

	// VA-API drivers may use separate layers with one plane each, or a single
	// layer with multiple planes. We need to handle both.
	uint32_t drm_format = get_drm_frame_format(drm_frame_desc);
	if (drm_format == DRM_FORMAT_INVALID) {
		fprintf(stderr, "Failed to get DRM frame format\n");
		return 1;
	}
	fprintf(stderr, "DRM format: 0x%X\n", drm_format);

	for (int i = 0; i < drm_frame_desc->nb_objects; i++) {
		close(drm_frame_desc->objects[i].fd);
		drm_frame_desc->objects[i].fd = -1;