improve format support

This commit is contained in:
Wim Taymans 2016-08-26 20:26:34 +02:00
parent a973007a49
commit ee17176faf
8 changed files with 222 additions and 91 deletions

View file

@ -36,7 +36,7 @@ typedef enum {
SPA_PROP_ID_AUDIO_RATE,
SPA_PROP_ID_AUDIO_CHANNELS,
SPA_PROP_ID_AUDIO_CHANNEL_MASK,
SPA_PROP_ID_AUDIO_RAW_INFO,
SPA_PROP_ID_AUDIO_INFO_RAW,
} SpaPropIdAudio;
SpaResult spa_prop_info_fill_audio (SpaPropInfo *info,

View file

@ -37,25 +37,48 @@ typedef enum {
SPA_MEDIA_TYPE_IMAGE = 3,
} SpaMediaType;
typedef enum {
SPA_MEDIA_SUBTYPE_INVALID = 0,
SPA_MEDIA_SUBTYPE_RAW = 1,
SPA_MEDIA_SUBTYPE_H264 = 2,
SPA_MEDIA_SUBTYPE_MJPG = 3,
SPA_MEDIA_SUBTYPE_DV = 4,
SPA_MEDIA_SUBTYPE_MPEGTS = 5,
SPA_MEDIA_SUBTYPE_H263 = 6,
SPA_MEDIA_SUBTYPE_MPEG1 = 7,
SPA_MEDIA_SUBTYPE_MPEG2 = 8,
SPA_MEDIA_SUBTYPE_MPEG4 = 9,
SPA_MEDIA_SUBTYPE_XVID = 10,
SPA_MEDIA_SUBTYPE_VC1 = 11,
SPA_MEDIA_SUBTYPE_VP8 = 12,
SPA_MEDIA_SUBTYPE_VP9 = 13,
SPA_MEDIA_SUBTYPE_JPEG = 14,
SPA_MEDIA_SUBTYPE_BAYER = 15,
SPA_MEDIA_SUBTYPE_MP3 = 16,
SPA_MEDIA_SUBTYPE_AAC = 17,
#define SPA_MEDIA_SUBTYPE_ANY_FIRST 1
SPA_MEDIA_SUBTYPE_RAW = SPA_MEDIA_SUBTYPE_ANY_FIRST,
#define SPA_MEDIA_SUBTYPE_ANY_LAST SPA_MEDIA_SUBTYPE_RAW
/* VIDEO */
#define SPA_MEDIA_SUBTYPE_VIDEO_FIRST 20
SPA_MEDIA_SUBTYPE_H264 = SPA_MEDIA_SUBTYPE_VIDEO_FIRST,
SPA_MEDIA_SUBTYPE_MJPG,
SPA_MEDIA_SUBTYPE_DV,
SPA_MEDIA_SUBTYPE_MPEGTS,
SPA_MEDIA_SUBTYPE_H263,
SPA_MEDIA_SUBTYPE_MPEG1,
SPA_MEDIA_SUBTYPE_MPEG2,
SPA_MEDIA_SUBTYPE_MPEG4,
SPA_MEDIA_SUBTYPE_XVID,
SPA_MEDIA_SUBTYPE_VC1,
SPA_MEDIA_SUBTYPE_VP8,
SPA_MEDIA_SUBTYPE_VP9,
SPA_MEDIA_SUBTYPE_JPEG,
SPA_MEDIA_SUBTYPE_BAYER,
#define SPA_MEDIA_SUBTYPE_VIDEO_LAST SPA_MEDIA_SUBTYPE_BAYER
/* AUDIO */
#define SPA_MEDIA_SUBTYPE_AUDIO_FIRST 200
SPA_MEDIA_SUBTYPE_MP3 = SPA_MEDIA_SUBTYPE_AUDIO_FIRST,
SPA_MEDIA_SUBTYPE_AAC,
SPA_MEDIA_SUBTYPE_VORBIS,
SPA_MEDIA_SUBTYPE_WMA,
SPA_MEDIA_SUBTYPE_RA,
SPA_MEDIA_SUBTYPE_SBC,
SPA_MEDIA_SUBTYPE_ADPCM,
SPA_MEDIA_SUBTYPE_G723,
SPA_MEDIA_SUBTYPE_G726,
SPA_MEDIA_SUBTYPE_G729,
SPA_MEDIA_SUBTYPE_AMR,
SPA_MEDIA_SUBTYPE_GSM,
#define SPA_MEDIA_SUBTYPE_AUDIO_LAST SPA_MEDIA_SUBTYPE_GSM
} SpaMediaSubType;
/**

View file

@ -24,12 +24,12 @@
extern "C" {
#endif
typedef struct _SpaVideoInfoJPEG SpaVideoInfoJPEG;
typedef struct _SpaVideoInfoMJPG SpaVideoInfoMJPG;
#include <spa/format.h>
#include <spa/video/format.h>
struct _SpaVideoInfoJPEG {
struct _SpaVideoInfoMJPG {
SpaRectangle size;
SpaFraction framerate;
SpaFraction max_framerate;

View file

@ -45,7 +45,8 @@ typedef enum {
SPA_PROP_ID_VIDEO_COLOR_MATRIX,
SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION,
SPA_PROP_ID_VIDEO_COLOR_PRIMARIES,
SPA_PROP_ID_VIDEO_RAW_INFO,
SPA_PROP_ID_VIDEO_INFO_RAW,
SPA_PROP_ID_VIDEO_INFO_MJPG,
} SpaPropIdVideo;
SpaResult spa_prop_info_fill_video (SpaPropInfo *info,
@ -62,7 +63,7 @@ struct _SpaFormatVideo {
SpaFormat format;
union {
SpaVideoInfoRaw raw;
SpaVideoInfoJPEG jpeg;
SpaVideoInfoMJPG mjpg;
} info;
};

View file

@ -173,7 +173,7 @@ static const SpaPropInfo format_prop_info[] =
SPA_PROP_TYPE_BITMASK, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
NULL },
{ SPA_PROP_ID_AUDIO_RAW_INFO, 0,
{ SPA_PROP_ID_AUDIO_INFO_RAW, 0,
"info", "the SpaAudioInfoRaw structure",
SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_POINTER, sizeof (SpaAudioInfoRaw),
@ -186,26 +186,38 @@ spa_prop_info_fill_audio (SpaPropInfo *info,
SpaPropIdAudio id,
size_t offset)
{
unsigned int i;
int i;
if (info == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
for (i = 0; i < SPA_N_ELEMENTS (format_prop_info); i++) {
if (format_prop_info[i].id == id) {
i = id - SPA_PROP_ID_MEDIA_CUSTOM_START;
if (i < 0 || i >= SPA_N_ELEMENTS (format_prop_info))
return SPA_RESULT_INVALID_PROPERTY_INDEX;
memcpy (info, &format_prop_info[i], sizeof (SpaPropInfo));
info->offset = offset;
return SPA_RESULT_OK;
}
}
return SPA_RESULT_INVALID_PROPERTY_INDEX;
}
SpaResult
spa_format_audio_init (SpaMediaType type,
SpaMediaSubType subtype,
SpaFormatAudio *format)
{
SpaPropInfo *prop_info = NULL;
unsigned int n_prop_info = 0;
int i;
if (type != SPA_MEDIA_TYPE_AUDIO)
return SPA_RESULT_INVALID_ARGUMENTS;
switch (subtype) {
case SPA_MEDIA_SUBTYPE_RAW:
{
static SpaPropInfo raw_format_prop_info[] =
{
{ SPA_PROP_ID_AUDIO_FORMAT, offsetof (SpaFormatAudio, info.raw.format), },
@ -214,24 +226,44 @@ spa_format_audio_init (SpaMediaType type,
{ SPA_PROP_ID_AUDIO_RATE, offsetof (SpaFormatAudio, info.raw.rate), },
{ SPA_PROP_ID_AUDIO_CHANNELS, offsetof (SpaFormatAudio, info.raw.channels), },
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, offsetof (SpaFormatAudio, info.raw.channel_mask), },
{ SPA_PROP_ID_AUDIO_RAW_INFO, offsetof (SpaFormatAudio, info), },
{ SPA_PROP_ID_AUDIO_INFO_RAW, offsetof (SpaFormatAudio, info), },
};
prop_info = raw_format_prop_info;
n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
format->format.props.unset_mask = (1 << 0) | (1 << 2) | (1 << 3) | (1 << 4);
format->info.raw = default_raw_info;
break;
}
if (raw_format_prop_info[0].name == NULL) {
int i;
case SPA_MEDIA_SUBTYPE_MP3:
case SPA_MEDIA_SUBTYPE_AAC:
case SPA_MEDIA_SUBTYPE_VORBIS:
case SPA_MEDIA_SUBTYPE_WMA:
case SPA_MEDIA_SUBTYPE_RA:
case SPA_MEDIA_SUBTYPE_SBC:
case SPA_MEDIA_SUBTYPE_ADPCM:
case SPA_MEDIA_SUBTYPE_G723:
case SPA_MEDIA_SUBTYPE_G726:
case SPA_MEDIA_SUBTYPE_G729:
case SPA_MEDIA_SUBTYPE_AMR:
case SPA_MEDIA_SUBTYPE_GSM:
break;
for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++)
spa_prop_info_fill_audio (&raw_format_prop_info[i],
raw_format_prop_info[i].id,
raw_format_prop_info[i].offset);
default:
return SPA_RESULT_INVALID_ARGUMENTS;
}
if (prop_info && prop_info[0].name == NULL) {
for (i = 0; i < n_prop_info; i++)
spa_prop_info_fill_audio (&prop_info[i],
prop_info[i].id,
prop_info[i].offset);
}
format->format.media_type = type;
format->format.media_subtype = subtype;
format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
format->format.props.prop_info = raw_format_prop_info;
format->format.props.unset_mask = (1 << 0) | (1 << 2) | (1 << 3) | (1 << 4);
format->info.raw = default_raw_info;
format->format.props.n_prop_info = n_prop_info;
format->format.props.prop_info = prop_info;
return SPA_RESULT_OK;
}
@ -255,7 +287,7 @@ spa_format_audio_parse (const SpaFormat *format,
aformat);
props = &format->props;
if ((res = spa_props_get_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_RAW_INFO), &value)) < 0)
if ((res = spa_props_get_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_INFO_RAW), &value)) < 0)
goto fallback;
if (value.type != SPA_PROP_TYPE_POINTER || value.size != sizeof (SpaAudioInfoRaw))

View file

@ -168,18 +168,23 @@ spa_debug_dump_mem (const void *mem, size_t size)
struct media_type_name {
const char *name;
unsigned int first;
unsigned int last;
unsigned int idx;
} media_type_names[] = {
{ "invalid" },
{ "audio" },
{ "video" },
{ "image" },
{ "invalid", 0, 0, 0 },
{ "audio", SPA_MEDIA_SUBTYPE_AUDIO_FIRST, SPA_MEDIA_SUBTYPE_AUDIO_LAST, 16 },
{ "video", SPA_MEDIA_SUBTYPE_VIDEO_FIRST, SPA_MEDIA_SUBTYPE_VIDEO_LAST, 2 },
{ "image", 0, 0 },
};
struct media_subtype_name {
const char *name;
} media_subtype_names[] = {
{ "invalid" },
{ "raw" },
{ "h264" },
{ "mjpg" },
{ "dv" },
@ -194,8 +199,19 @@ struct media_subtype_name {
{ "vp9" },
{ "jpeg" },
{ "bayer" },
{ "mp3" },
{ "aac" },
{ "vorbis" },
{ "wma" },
{ "ra" },
{ "sbc" },
{ "adpcm" },
{ "g723" },
{ "g726" },
{ "g729" },
{ "amr" },
{ "gsm" },
};
struct prop_type_name {
@ -400,7 +416,7 @@ SpaResult
spa_debug_format (const SpaFormat *format)
{
const SpaProps *props;
int i;
int i, first, last, idx;
const char *media_type;
const char *media_subtype;
@ -409,13 +425,22 @@ spa_debug_format (const SpaFormat *format)
props = &format->props;
if (format->media_type > 0 && format->media_type < SPA_N_ELEMENTS (media_type_names))
if (format->media_type > 0 && format->media_type < SPA_N_ELEMENTS (media_type_names)) {
media_type = media_type_names[format->media_type].name;
else
first = media_type_names[format->media_type].first;
last = media_type_names[format->media_type].last;
idx = media_type_names[format->media_type].idx;
}
else {
media_type = "unknown";
idx = first = last = -1;
}
if (format->media_subtype > 0 && format->media_subtype < SPA_N_ELEMENTS (media_subtype_names))
if (format->media_subtype >= SPA_MEDIA_SUBTYPE_ANY_FIRST &&
format->media_subtype <= SPA_MEDIA_SUBTYPE_ANY_LAST) {
media_subtype = media_subtype_names[format->media_subtype].name;
} else if (format->media_subtype >= first && format->media_subtype <= last)
media_subtype = media_subtype_names[format->media_subtype - first + idx].name;
else
media_subtype = "unknown";

View file

@ -457,7 +457,7 @@ static const SpaPropInfo format_prop_info[] =
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_primaries_range), color_primaries_range,
NULL },
{ SPA_PROP_ID_VIDEO_RAW_INFO, 0,
{ SPA_PROP_ID_VIDEO_INFO_RAW, 0,
"info", "the SpaVideoRawInfo structure",
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
SPA_PROP_TYPE_POINTER, sizeof (SpaVideoInfoRaw),
@ -491,7 +491,17 @@ spa_format_video_init (SpaMediaType type,
SpaMediaSubType subtype,
SpaFormatVideo *format)
{
static SpaPropInfo raw_format_prop_info[] = {
SpaPropInfo *prop_info = NULL;
unsigned int n_prop_info = 0;
int i;
if (type != SPA_MEDIA_TYPE_VIDEO)
return SPA_RESULT_INVALID_ARGUMENTS;
switch (subtype) {
case SPA_MEDIA_SUBTYPE_RAW:
{
static SpaPropInfo raw_prop_info[] = {
{ SPA_PROP_ID_VIDEO_FORMAT, offsetof (SpaFormatVideo, info.raw.format) },
{ SPA_PROP_ID_VIDEO_SIZE, offsetof (SpaFormatVideo, info.raw.size) },
{ SPA_PROP_ID_VIDEO_FRAMERATE, offsetof (SpaFormatVideo, info.raw.framerate) },
@ -506,23 +516,62 @@ spa_format_video_init (SpaMediaType type,
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, offsetof (SpaFormatVideo, info.raw.color_matrix) },
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, offsetof (SpaFormatVideo, info.raw.transfer_function) },
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, offsetof (SpaFormatVideo, info.raw.color_primaries) },
{ SPA_PROP_ID_VIDEO_RAW_INFO, offsetof (SpaFormatVideo, info.raw ) },
{ SPA_PROP_ID_VIDEO_INFO_RAW, offsetof (SpaFormatVideo, info.raw) },
};
prop_info = raw_prop_info;
n_prop_info = SPA_N_ELEMENTS (raw_prop_info);
format->format.props.unset_mask = (1 << 14)-1;
format->info.raw = default_raw_info;
break;
}
if (raw_format_prop_info[0].name == NULL) {
int i;
for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++)
spa_prop_info_fill_video (&raw_format_prop_info[i],
raw_format_prop_info[i].id,
raw_format_prop_info[i].offset);
case SPA_MEDIA_SUBTYPE_H264:
return SPA_RESULT_NOT_IMPLEMENTED;
case SPA_MEDIA_SUBTYPE_MJPG:
{
static SpaPropInfo mjpg_prop_info[] = {
{ SPA_PROP_ID_VIDEO_SIZE, offsetof (SpaFormatVideo, info.mjpg.size) },
{ SPA_PROP_ID_VIDEO_FRAMERATE, offsetof (SpaFormatVideo, info.mjpg.framerate) },
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, offsetof (SpaFormatVideo, info.mjpg.max_framerate) },
{ SPA_PROP_ID_VIDEO_INFO_MJPG, offsetof (SpaFormatVideo, info.mjpg) },
};
prop_info = mjpg_prop_info;
n_prop_info = SPA_N_ELEMENTS (mjpg_prop_info);
format->format.props.unset_mask = (1 << 3)-1;
format->info.raw = default_raw_info;
break;
}
case SPA_MEDIA_SUBTYPE_DV:
case SPA_MEDIA_SUBTYPE_MPEGTS:
case SPA_MEDIA_SUBTYPE_H263:
case SPA_MEDIA_SUBTYPE_MPEG1:
case SPA_MEDIA_SUBTYPE_MPEG2:
case SPA_MEDIA_SUBTYPE_MPEG4:
case SPA_MEDIA_SUBTYPE_XVID:
case SPA_MEDIA_SUBTYPE_VC1:
case SPA_MEDIA_SUBTYPE_VP8:
case SPA_MEDIA_SUBTYPE_VP9:
case SPA_MEDIA_SUBTYPE_JPEG:
case SPA_MEDIA_SUBTYPE_BAYER:
return SPA_RESULT_NOT_IMPLEMENTED;
default:
return SPA_RESULT_INVALID_ARGUMENTS;
}
if (prop_info && prop_info[0].name == NULL) {
for (i = 0; i < n_prop_info; i++)
spa_prop_info_fill_video (&prop_info[i],
prop_info[i].id,
prop_info[i].offset);
}
format->format.media_type = type;
format->format.media_subtype = subtype;
format->format.props.n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
format->format.props.prop_info = raw_format_prop_info;
format->format.props.unset_mask = (1 << 14)-1;
format->info.raw = default_raw_info;
format->format.props.n_prop_info = n_prop_info;
format->format.props.prop_info = prop_info;
return SPA_RESULT_OK;
}
@ -546,7 +595,7 @@ spa_format_video_parse (const SpaFormat *format,
vformat);
props = &format->props;
if ((res = spa_props_get_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_RAW_INFO), &value)) < 0)
if ((res = spa_props_get_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_INFO_RAW), &value)) < 0)
goto fallback;
if (value.type != SPA_PROP_TYPE_POINTER)

View file

@ -463,7 +463,7 @@ static int
spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
{
SpaV4l2State *state = &this->state[0];
int cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT;
int cmd;
struct v4l2_format reqfmt, fmt;
struct v4l2_streamparm streamparm;
const FormatInfo *info = NULL;
@ -500,6 +500,7 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
if (spa_v4l2_open (this) < 0)
return -1;
cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT;
if (xioctl (state->fd, cmd, &fmt) < 0) {
perror ("VIDIOC_S_FMT");
return -1;