File: ffmpeg.c

package info (click to toggle)
pipewire 1.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 17,852 kB
  • sloc: ansic: 309,458; cpp: 2,812; xml: 407; python: 243; sh: 214; makefile: 176; pascal: 85
file content (143 lines) | stat: -rw-r--r-- 2,933 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* Spa FFmpeg support */
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
/* SPDX-License-Identifier: MIT */

#include <errno.h>
#include <stdio.h>

#include <spa/support/plugin.h>
#include <spa/support/log.h>
#include <spa/node/node.h>

#include <libavcodec/avcodec.h>

#include "ffmpeg.h"

static int
ffmpeg_dec_init(const struct spa_handle_factory *factory,
		struct spa_handle *handle,
		const struct spa_dict *info,
		const struct spa_support *support,
		uint32_t n_support)
{
	if (factory == NULL || handle == NULL)
		return -EINVAL;

	return spa_ffmpeg_dec_init(handle, info, support, n_support);
}

static int
ffmpeg_enc_init(const struct spa_handle_factory *factory,
		struct spa_handle *handle,
		const struct spa_dict *info,
		const struct spa_support *support,
		uint32_t n_support)
{
	if (factory == NULL || handle == NULL)
		return -EINVAL;

	return spa_ffmpeg_enc_init(handle, info, support, n_support);
}

static const struct spa_interface_info ffmpeg_interfaces[] = {
	{SPA_TYPE_INTERFACE_Node, },
};

static int
ffmpeg_enum_interface_info(const struct spa_handle_factory *factory,
			   const struct spa_interface_info **info,
			   uint32_t *index)
{
	if (factory == NULL || info == NULL || index == NULL)
		return -EINVAL;

	if (*index < SPA_N_ELEMENTS(ffmpeg_interfaces))
		*info = &ffmpeg_interfaces[(*index)++];
	else
		return 0;

	return 1;
}

#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 10, 100)
static const AVCodec *find_codec_by_index(uint32_t index)
{
	static void *av_iter_data;
	static uint32_t next_index;

	const AVCodec *c = NULL;

	if (index == 0) {
		av_iter_data = NULL;
		next_index = 0;
	}

	while (next_index <= index) {
		c = av_codec_iterate(&av_iter_data);
		next_index += 1;

		if (!c)
			break;
	}

	return c;
}
#else
static const AVCodec *find_codec_by_index(uint32_t index)
{
	static const AVCodec *last_codec;
	static uint32_t next_index;

	if (index == 0) {
		last_codec = NULL;
		next_index = 0;
	}

	while (next_index <= index) {
		last_codec = av_codec_next(last_codec);
		next_index += 1;

		if (!last_codec)
			break;
	}

	return last_codec;
}
#endif

SPA_LOG_TOPIC_ENUM_DEFINE_REGISTERED;

SPA_EXPORT
int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
{
	static char name[128];
	static struct spa_handle_factory f = {
		SPA_VERSION_HANDLE_FACTORY,
		.name = name,
		.enum_interface_info = ffmpeg_enum_interface_info,
	};

#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
	avcodec_register_all();
#endif

	const AVCodec *c = find_codec_by_index(*index);

	if (c == NULL)
		return 0;

	if (av_codec_is_encoder(c)) {
		snprintf(name, sizeof(name), "encoder.%s", c->name);
		f.get_size = spa_ffmpeg_enc_get_size;
		f.init = ffmpeg_enc_init;
	} else {
		snprintf(name, sizeof(name), "decoder.%s", c->name);
		f.get_size = spa_ffmpeg_dec_get_size;
		f.init = ffmpeg_dec_init;
	}

	*factory = &f;
	(*index)++;

	return 1;
}