mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
Rework formats
Use a POD for the format body. This allows us to more easily build and copy the formats. Remove obsolete code to make video and audio formats. Use SpaVideo/AudioInfo to keep track of formats. Make functions to parse the format into the structures. Update plugins
This commit is contained in:
parent
7fc73953cd
commit
16b62de53a
34 changed files with 1096 additions and 1579 deletions
|
|
@ -95,24 +95,19 @@ pinos_serialize_format_get_size (const SpaFormat *format)
|
|||
if (format == NULL)
|
||||
return 0;
|
||||
|
||||
return pinos_serialize_props_get_size (&format->props) - sizeof (SpaProps) + sizeof (SpaFormat);
|
||||
return SPA_FORMAT_SIZE (format);
|
||||
}
|
||||
|
||||
size_t
|
||||
pinos_serialize_format_serialize (void *dest, const SpaFormat *format)
|
||||
{
|
||||
SpaFormat *tf;
|
||||
size_t size;
|
||||
|
||||
if (format == NULL)
|
||||
return 0;
|
||||
|
||||
tf = dest;
|
||||
tf->media_type = format->media_type;
|
||||
tf->media_subtype = format->media_subtype;
|
||||
|
||||
dest = SPA_MEMBER (tf, offsetof (SpaFormat, props), void);
|
||||
size = pinos_serialize_props_serialize (dest, &format->props) - sizeof (SpaProps) + sizeof (SpaFormat);
|
||||
size = SPA_FORMAT_SIZE (format);
|
||||
memcpy (dest, format, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
|
@ -120,12 +115,7 @@ pinos_serialize_format_serialize (void *dest, const SpaFormat *format)
|
|||
SpaFormat *
|
||||
pinos_serialize_format_deserialize (void *src, off_t offset)
|
||||
{
|
||||
SpaFormat *f;
|
||||
|
||||
f = SPA_MEMBER (src, offset, SpaFormat);
|
||||
pinos_serialize_props_deserialize (f, offsetof (SpaFormat, props));
|
||||
|
||||
return f;
|
||||
return SPA_MEMBER (src, offset, SpaFormat);
|
||||
}
|
||||
|
||||
SpaFormat *
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "gstpinosformat.h"
|
||||
|
||||
#if 0
|
||||
static guint
|
||||
calc_range_size (const GValue *val)
|
||||
{
|
||||
|
|
@ -278,10 +279,12 @@ handle_video_framerate (ConvertData *d)
|
|||
d->pi++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static SpaFormat *
|
||||
convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
||||
{
|
||||
#if 0
|
||||
const GValue *val;
|
||||
guint size, n_infos = 0, n_ranges = 0, n_datas = 0;
|
||||
ConvertData d;
|
||||
|
|
@ -425,6 +428,8 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
|
|||
handle_video_framerate (&d);
|
||||
}
|
||||
return d.f;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SpaFormat *
|
||||
|
|
@ -471,12 +476,12 @@ gst_caps_to_format_all (GstCaps *caps)
|
|||
}
|
||||
|
||||
GstCaps *
|
||||
gst_caps_from_format (SpaFormat *format)
|
||||
gst_caps_from_format (const SpaFormat *format)
|
||||
{
|
||||
GstCaps *res = NULL;
|
||||
|
||||
if (format->media_type == SPA_MEDIA_TYPE_VIDEO) {
|
||||
SpaFormatVideo f;
|
||||
SpaVideoInfo f;
|
||||
|
||||
if (spa_format_video_parse (format, &f) < 0)
|
||||
return NULL;
|
||||
|
|
@ -506,7 +511,7 @@ gst_caps_from_format (SpaFormat *format)
|
|||
NULL);
|
||||
}
|
||||
} else if (format->media_type == SPA_MEDIA_TYPE_AUDIO) {
|
||||
SpaFormatAudio f;
|
||||
SpaAudioInfo f;
|
||||
|
||||
if (spa_format_audio_parse (format, &f) < 0)
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ G_BEGIN_DECLS
|
|||
SpaFormat * gst_caps_to_format (GstCaps *caps, guint index);
|
||||
GPtrArray * gst_caps_to_format_all (GstCaps *caps);
|
||||
|
||||
GstCaps * gst_caps_from_format (SpaFormat *format);
|
||||
GstCaps * gst_caps_from_format (const SpaFormat *format);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <pinos/server/core.h>
|
||||
#include <pinos/server/data-loop.h>
|
||||
#include <pinos/server/client-node.h>
|
||||
#include <spa/lib/debug.h>
|
||||
|
||||
typedef struct {
|
||||
PinosGlobal this;
|
||||
|
|
|
|||
|
|
@ -59,9 +59,10 @@ pinos_link_update_state (PinosLink *link,
|
|||
PinosLinkState old = link->state;
|
||||
|
||||
if (state != old) {
|
||||
pinos_log_debug ("link %p: update state %s -> %s", link,
|
||||
pinos_log_debug ("link %p: update state %s -> %s (%s)", link,
|
||||
pinos_link_state_as_string (old),
|
||||
pinos_link_state_as_string (state));
|
||||
pinos_link_state_as_string (state),
|
||||
error);
|
||||
|
||||
link->state = state;
|
||||
if (link->error)
|
||||
|
|
@ -97,8 +98,10 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
0,
|
||||
NULL,
|
||||
&error);
|
||||
if (format == NULL)
|
||||
if (format == NULL) {
|
||||
asprintf (&error, "no common format found");
|
||||
goto error;
|
||||
}
|
||||
|
||||
pinos_log_debug ("link %p: doing set format", this);
|
||||
if (pinos_log_level_enabled (SPA_LOG_LEVEL_DEBUG))
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <pinos/client/pinos.h>
|
||||
#include <pinos/client/sig.h>
|
||||
#include <spa/lib/debug.h>
|
||||
|
||||
typedef struct {
|
||||
bool running;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ extern "C" {
|
|||
#include <spa/format.h>
|
||||
#include <spa/audio/raw.h>
|
||||
|
||||
typedef struct _SpaFormatAudio SpaFormatAudio;
|
||||
typedef struct _SpaAudioInfo SpaAudioInfo;
|
||||
|
||||
typedef enum {
|
||||
SPA_PROP_ID_AUDIO_INFO = SPA_PROP_ID_MEDIA_CUSTOM_START,
|
||||
|
|
@ -39,24 +39,16 @@ typedef enum {
|
|||
SPA_PROP_ID_AUDIO_CHANNEL_MASK,
|
||||
} SpaPropIdAudio;
|
||||
|
||||
SpaResult spa_prop_info_fill_audio (SpaPropInfo *info,
|
||||
SpaPropIdAudio id,
|
||||
size_t offset);
|
||||
|
||||
struct _SpaFormatAudio {
|
||||
SpaFormat format;
|
||||
struct _SpaAudioInfo {
|
||||
SpaMediaType media_type;
|
||||
SpaMediaSubType media_subtype;
|
||||
union {
|
||||
SpaAudioInfoRaw raw;
|
||||
} info;
|
||||
};
|
||||
|
||||
SpaResult spa_format_audio_init (SpaMediaType type,
|
||||
SpaMediaSubType subtype,
|
||||
SpaFormatAudio *format);
|
||||
SpaResult spa_format_audio_parse (const SpaFormat *format,
|
||||
SpaFormatAudio *aformat);
|
||||
SpaResult spa_format_audio_filter (SpaFormatAudio *format,
|
||||
const SpaFormat *filter);
|
||||
SpaAudioInfo *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
179
spa/include/spa/format-builder.h
Normal file
179
spa/include/spa/format-builder.h
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/* Simple Plugin API
|
||||
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SPA_FORMAT_BUILDER_H__
|
||||
#define __SPA_FORMAT_BUILDER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <spa/format.h>
|
||||
#include <spa/pod-builder.h>
|
||||
|
||||
static inline off_t
|
||||
spa_pod_builder_push_format (SpaPODBuilder *builder,
|
||||
SpaPODFrame *frame,
|
||||
uint32_t media_type,
|
||||
uint32_t media_subtype)
|
||||
{
|
||||
SpaFormat f = { media_type, media_subtype, { { 0, 0 }, { 0, 0 } } };
|
||||
off_t offset;
|
||||
|
||||
offset = spa_pod_builder_raw (builder, &f, sizeof(f) - sizeof(SpaPODObject), false);
|
||||
if (spa_pod_builder_push_object (builder, frame, 0, 0) == -1)
|
||||
offset = -1;
|
||||
return offset;
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_pod_builder_format_propv (SpaPODBuilder *builder,
|
||||
uint32_t propid,
|
||||
va_list args)
|
||||
{
|
||||
while (propid != 0) {
|
||||
int type, n_alternatives = -1;
|
||||
SpaPODProp *prop = NULL;
|
||||
SpaPODFrame f;
|
||||
off_t off;
|
||||
|
||||
if ((off = spa_pod_builder_push_prop (builder, &f, propid, SPA_POD_PROP_FLAG_READWRITE)) != -1)
|
||||
prop = SPA_MEMBER (builder->data, off, SpaPODProp);
|
||||
|
||||
type = va_arg (args, uint32_t);
|
||||
|
||||
while (n_alternatives != 0) {
|
||||
switch (type) {
|
||||
case SPA_POD_TYPE_INVALID:
|
||||
break;
|
||||
case SPA_POD_TYPE_BOOL:
|
||||
spa_pod_builder_bool (builder, va_arg (args, int));
|
||||
break;
|
||||
case SPA_POD_TYPE_INT:
|
||||
spa_pod_builder_int (builder, va_arg (args, int32_t));
|
||||
break;
|
||||
case SPA_POD_TYPE_LONG:
|
||||
spa_pod_builder_long (builder, va_arg (args, int64_t));
|
||||
break;
|
||||
case SPA_POD_TYPE_FLOAT:
|
||||
spa_pod_builder_float (builder, va_arg (args, double));
|
||||
break;
|
||||
case SPA_POD_TYPE_DOUBLE:
|
||||
spa_pod_builder_double (builder, va_arg (args, double));
|
||||
break;
|
||||
case SPA_POD_TYPE_STRING:
|
||||
{
|
||||
const char *str = va_arg (args, char *);
|
||||
uint32_t len = va_arg (args, uint32_t);
|
||||
spa_pod_builder_string (builder, str, len);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_RECTANGLE:
|
||||
{
|
||||
uint32_t width = va_arg (args, uint32_t), height = va_arg (args, uint32_t);
|
||||
spa_pod_builder_rectangle (builder, width, height);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_FRACTION:
|
||||
{
|
||||
uint32_t num = va_arg (args, uint32_t), denom = va_arg (args, uint32_t);
|
||||
spa_pod_builder_fraction (builder, num, denom);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_BITMASK:
|
||||
break;
|
||||
case SPA_POD_TYPE_ARRAY:
|
||||
case SPA_POD_TYPE_STRUCT:
|
||||
case SPA_POD_TYPE_OBJECT:
|
||||
case SPA_POD_TYPE_PROP:
|
||||
break;
|
||||
}
|
||||
if (n_alternatives == -1) {
|
||||
uint32_t flags = va_arg (args, uint32_t);
|
||||
if (prop)
|
||||
prop->body.flags = flags;
|
||||
|
||||
switch (flags & SPA_POD_PROP_RANGE_MASK) {
|
||||
case SPA_POD_PROP_RANGE_NONE:
|
||||
n_alternatives = 0;
|
||||
break;
|
||||
case SPA_POD_PROP_RANGE_MIN_MAX:
|
||||
n_alternatives = 2;
|
||||
break;
|
||||
case SPA_POD_PROP_RANGE_STEP:
|
||||
n_alternatives = 3;
|
||||
break;
|
||||
case SPA_POD_PROP_RANGE_ENUM:
|
||||
case SPA_POD_PROP_RANGE_MASK:
|
||||
n_alternatives = va_arg (args, int);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
n_alternatives--;
|
||||
}
|
||||
spa_pod_builder_pop (builder, &f);
|
||||
|
||||
propid = va_arg (args, uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_pod_builder_format_prop (SpaPODBuilder *builder,
|
||||
uint32_t propid, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, propid);
|
||||
spa_pod_builder_format_propv (builder, propid, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
static inline off_t
|
||||
spa_pod_builder_format (SpaPODBuilder *builder,
|
||||
uint32_t media_type,
|
||||
uint32_t media_subtype,
|
||||
uint32_t propid, ...)
|
||||
{
|
||||
SpaPODFrame f;
|
||||
va_list args;
|
||||
off_t off;
|
||||
|
||||
off = spa_pod_builder_push_format (builder, &f, media_type, media_subtype);
|
||||
|
||||
va_start (args, propid);
|
||||
spa_pod_builder_format_propv (builder, propid, args);
|
||||
va_end (args);
|
||||
|
||||
spa_pod_builder_pop (builder, &f);
|
||||
|
||||
return off;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_format_filter (const SpaFormat *format,
|
||||
const SpaFormat *filter,
|
||||
SpaPODBuilder *result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __SPA_FORMAT_BUILDER_H__ */
|
||||
|
|
@ -26,8 +26,10 @@ extern "C" {
|
|||
|
||||
typedef struct _SpaFormat SpaFormat;
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <spa/defs.h>
|
||||
#include <spa/props.h>
|
||||
#include <spa/pod.h>
|
||||
|
||||
typedef enum {
|
||||
SPA_MEDIA_TYPE_INVALID = 0,
|
||||
|
|
@ -36,7 +38,6 @@ typedef enum {
|
|||
SPA_MEDIA_TYPE_IMAGE = 3,
|
||||
} SpaMediaType;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SPA_MEDIA_SUBTYPE_INVALID = 0,
|
||||
|
||||
|
|
@ -80,41 +81,33 @@ typedef enum {
|
|||
|
||||
} SpaMediaSubType;
|
||||
|
||||
/**
|
||||
* SpaFormat:
|
||||
* @media_type: media type
|
||||
* @media_subtype: subtype
|
||||
* @props: properties
|
||||
*/
|
||||
struct _SpaFormat {
|
||||
SpaMediaType media_type;
|
||||
SpaMediaSubType media_subtype;
|
||||
SpaProps props;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SPA_PROP_ID_INVALID = 0,
|
||||
SPA_PROP_ID_MEDIA_CUSTOM_START = 200,
|
||||
} SpaFormatProps;
|
||||
|
||||
/**
|
||||
* SpaFormat:
|
||||
* @media_type: media type
|
||||
* @media_subtype: subtype
|
||||
* @pod: POD object with properties
|
||||
*/
|
||||
struct _SpaFormat {
|
||||
uint32_t media_type;
|
||||
uint32_t media_subtype;
|
||||
SpaPODObject obj;
|
||||
};
|
||||
|
||||
|
||||
#define SPA_FORMAT_SIZE(f) (sizeof(SpaFormat) + (f)->obj.pod.size)
|
||||
|
||||
static inline SpaResult
|
||||
spa_format_fixate (SpaFormat *format)
|
||||
{
|
||||
if (format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
format->props.unset_mask = 0;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_format_filter (const SpaFormat *format,
|
||||
const SpaFormat *filter,
|
||||
SpaFormat **result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,34 +24,30 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _SpaPodFrame {
|
||||
struct _SpaPodFrame *parent;
|
||||
off_t offset;
|
||||
#include <spa/pod.h>
|
||||
|
||||
typedef struct _SpaPODFrame {
|
||||
struct _SpaPODFrame *parent;
|
||||
SpaPOD pod;
|
||||
off_t ref;
|
||||
} SpaPODFrame;
|
||||
|
||||
typedef struct {
|
||||
typedef struct _SpaPODBuilder {
|
||||
void *data;
|
||||
size_t size;
|
||||
off_t offset;
|
||||
SpaPODFrame *stack;
|
||||
off_t (*write) (struct _SpaPODBuilder *builder, off_t ref, const void *data, size_t size);
|
||||
} SpaPODBuilder;
|
||||
|
||||
static inline uint32_t
|
||||
spa_pod_builder_top (SpaPODBuilder *builder)
|
||||
{
|
||||
if (builder->stack && builder->stack->offset != -1)
|
||||
return SPA_MEMBER(builder->data, builder->stack->offset, SpaPOD)->type;
|
||||
return SPA_POD_TYPE_INVALID;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
spa_pod_builder_in_array (SpaPODBuilder *builder)
|
||||
{
|
||||
if (builder->stack && builder->stack->offset != -1) {
|
||||
SpaPOD *p = SPA_MEMBER(builder->data, builder->stack->offset, SpaPOD);
|
||||
if (p->type == SPA_POD_TYPE_ARRAY && p->size > 0)
|
||||
SpaPODFrame *f;
|
||||
if ((f = builder->stack)) {
|
||||
if (f->pod.type == SPA_POD_TYPE_ARRAY && f->pod.size > 0)
|
||||
return true;
|
||||
if (p->type == SPA_POD_TYPE_PROP && p->size > (sizeof (SpaPODPropBody) - sizeof(SpaPOD)))
|
||||
if (f->pod.type == SPA_POD_TYPE_PROP && f->pod.size > (sizeof (SpaPODPropBody) - sizeof(SpaPOD)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -60,12 +56,14 @@ spa_pod_builder_in_array (SpaPODBuilder *builder)
|
|||
static inline off_t
|
||||
spa_pod_builder_push (SpaPODBuilder *builder,
|
||||
SpaPODFrame *frame,
|
||||
off_t offset)
|
||||
const SpaPOD *pod,
|
||||
off_t ref)
|
||||
{
|
||||
frame->parent = builder->stack;
|
||||
frame->offset = offset;
|
||||
frame->pod = *pod;
|
||||
frame->ref = ref;
|
||||
builder->stack = frame;
|
||||
return offset;
|
||||
return ref;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -73,14 +71,13 @@ spa_pod_builder_advance (SpaPODBuilder *builder, uint32_t size, bool pad)
|
|||
{
|
||||
SpaPODFrame *f;
|
||||
|
||||
if (pad) {
|
||||
if (pad)
|
||||
size += SPA_ROUND_UP_N (builder->offset, 8) - builder->offset;
|
||||
}
|
||||
builder->offset += size;
|
||||
|
||||
for (f = builder->stack; f; f = f->parent) {
|
||||
if (f->offset != -1)
|
||||
SPA_MEMBER (builder->data, f->offset, SpaPOD)->size += size;
|
||||
if (size > 0) {
|
||||
builder->offset += size;
|
||||
for (f = builder->stack; f; f = f->parent)
|
||||
f->pod.size += size;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +85,12 @@ static inline void
|
|||
spa_pod_builder_pop (SpaPODBuilder *builder,
|
||||
SpaPODFrame *frame)
|
||||
{
|
||||
if (frame->ref != -1) {
|
||||
if (builder->write)
|
||||
builder->write (builder, frame->ref, &frame->pod, sizeof(SpaPOD));
|
||||
else
|
||||
memcpy (builder->data + frame->ref, &frame->pod, sizeof(SpaPOD));
|
||||
}
|
||||
builder->stack = frame->parent;
|
||||
spa_pod_builder_advance (builder, 0, true);
|
||||
}
|
||||
|
|
@ -95,16 +98,20 @@ spa_pod_builder_pop (SpaPODBuilder *builder,
|
|||
static inline off_t
|
||||
spa_pod_builder_raw (SpaPODBuilder *builder, const void *data, uint32_t size, bool pad)
|
||||
{
|
||||
off_t offset = builder->offset;
|
||||
off_t ref;
|
||||
|
||||
if (offset + size <= builder->size)
|
||||
memcpy (builder->data + offset, data, size);
|
||||
if (builder->write) {
|
||||
ref = builder->write (builder, -1, data, size);
|
||||
} else {
|
||||
ref = builder->offset;
|
||||
if (ref + size > builder->size)
|
||||
ref = -1;
|
||||
else
|
||||
offset = -1;
|
||||
|
||||
memcpy (builder->data + ref, data, size);
|
||||
}
|
||||
spa_pod_builder_advance (builder, size, pad);
|
||||
|
||||
return offset;
|
||||
return ref;
|
||||
}
|
||||
|
||||
static inline off_t
|
||||
|
|
@ -190,16 +197,16 @@ spa_pod_builder_string (SpaPODBuilder *builder, const char *str, uint32_t len)
|
|||
}
|
||||
|
||||
static inline off_t
|
||||
spa_pod_builder_rectangle (SpaPODBuilder *builder, SpaRectangle *val)
|
||||
spa_pod_builder_rectangle (SpaPODBuilder *builder, uint32_t width, uint32_t height)
|
||||
{
|
||||
const SpaPODRectangle p = { { sizeof (val), SPA_POD_TYPE_RECTANGLE }, *val };
|
||||
const SpaPODRectangle p = { { sizeof (SpaRectangle), SPA_POD_TYPE_RECTANGLE }, { width, height } };
|
||||
return spa_pod_builder_primitive (builder, &p.pod);
|
||||
}
|
||||
|
||||
static inline off_t
|
||||
spa_pod_builder_fraction (SpaPODBuilder *builder, SpaFraction *val)
|
||||
spa_pod_builder_fraction (SpaPODBuilder *builder, uint32_t num, uint32_t denom)
|
||||
{
|
||||
const SpaPODFraction p = { { sizeof (val), SPA_POD_TYPE_FRACTION }, *val };
|
||||
const SpaPODFraction p = { { sizeof (SpaFraction), SPA_POD_TYPE_FRACTION }, { num, denom } };
|
||||
return spa_pod_builder_primitive (builder, &p.pod);
|
||||
}
|
||||
|
||||
|
|
@ -208,7 +215,8 @@ spa_pod_builder_push_array (SpaPODBuilder *builder,
|
|||
SpaPODFrame *frame)
|
||||
{
|
||||
const SpaPODArray p = { { sizeof (SpaPODArrayBody) - sizeof (SpaPOD), SPA_POD_TYPE_ARRAY }, { { 0, 0 } } };
|
||||
return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false));
|
||||
return spa_pod_builder_push (builder, frame, &p.pod,
|
||||
spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false));
|
||||
}
|
||||
|
||||
static inline off_t
|
||||
|
|
@ -233,7 +241,8 @@ spa_pod_builder_push_struct (SpaPODBuilder *builder,
|
|||
SpaPODFrame *frame)
|
||||
{
|
||||
const SpaPODStruct p = { { 0, SPA_POD_TYPE_STRUCT } };
|
||||
return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p), false));
|
||||
return spa_pod_builder_push (builder, frame, &p.pod,
|
||||
spa_pod_builder_raw (builder, &p, sizeof(p), false));
|
||||
}
|
||||
|
||||
static inline off_t
|
||||
|
|
@ -243,7 +252,8 @@ spa_pod_builder_push_object (SpaPODBuilder *builder,
|
|||
uint32_t type)
|
||||
{
|
||||
const SpaPODObject p = { { sizeof (SpaPODObjectBody), SPA_POD_TYPE_OBJECT }, { id, type } };
|
||||
return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p), false));
|
||||
return spa_pod_builder_push (builder, frame, &p.pod,
|
||||
spa_pod_builder_raw (builder, &p, sizeof(p), false));
|
||||
}
|
||||
|
||||
static inline off_t
|
||||
|
|
@ -254,7 +264,8 @@ spa_pod_builder_push_prop (SpaPODBuilder *builder,
|
|||
{
|
||||
const SpaPODProp p = { { sizeof (SpaPODPropBody) - sizeof(SpaPOD), SPA_POD_TYPE_PROP},
|
||||
{ key, flags | SPA_POD_PROP_RANGE_NONE, { 0, 0 } } };
|
||||
return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false));
|
||||
return spa_pod_builder_push (builder, frame, &p.pod,
|
||||
spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ typedef enum {
|
|||
SPA_POD_TYPE_ARRAY,
|
||||
SPA_POD_TYPE_STRUCT,
|
||||
SPA_POD_TYPE_OBJECT,
|
||||
SPA_POD_TYPE_PROP
|
||||
SPA_POD_TYPE_PROP,
|
||||
SPA_POD_TYPE_BYTES
|
||||
} SpaPODType;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -122,17 +123,18 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
uint32_t key;
|
||||
#define SPA_POD_PROP_RANGE_NONE 0
|
||||
#define SPA_POD_PROP_RANGE_MIN_MAX 1
|
||||
#define SPA_POD_PROP_RANGE_STEP 2
|
||||
#define SPA_POD_PROP_RANGE_ENUM 3
|
||||
#define SPA_POD_PROP_RANGE_FLAGS 4
|
||||
#define SPA_POD_PROP_RANGE_MASK 0xf
|
||||
#define SPA_POD_PROP_FLAG_UNSET (1 << 4)
|
||||
#define SPA_POD_PROP_FLAG_OPTIONAL (1 << 5)
|
||||
#define SPA_POD_PROP_FLAG_READABLE (1 << 6)
|
||||
#define SPA_POD_PROP_FLAG_WRITABLE (1 << 7)
|
||||
#define SPA_POD_PROP_FLAG_READWRITE (SPA_POD_PROP_FLAG_READABLE | SPA_POD_PROP_FLAG_WRITABLE)
|
||||
#define SPA_POD_PROP_FLAG_DEPRECATED (1 << 8)
|
||||
#define SPA_POD_PROP_RANGE_NONE 0
|
||||
#define SPA_POD_PROP_RANGE_MIN_MAX 1
|
||||
#define SPA_POD_PROP_RANGE_STEP 2
|
||||
#define SPA_POD_PROP_RANGE_ENUM 3
|
||||
#define SPA_POD_PROP_RANGE_FLAGS 4
|
||||
uint32_t flags;
|
||||
SpaPOD value;
|
||||
/* array with elements of value.size follows,
|
||||
|
|
@ -144,6 +146,8 @@ typedef struct {
|
|||
SpaPODPropBody body;
|
||||
} SpaPODProp;
|
||||
|
||||
#define SPA_POD_PROP_N_VALUES(prop) (((prop)->pod.size - sizeof (SpaPODPropBody)) / (prop)->body.value.size)
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
|
|
@ -176,7 +180,7 @@ typedef struct {
|
|||
(iter) = SPA_MEMBER ((iter), (body)->value.size, __typeof__(*iter)))
|
||||
|
||||
static inline SpaPODProp *
|
||||
spa_pod_object_body_find_prop (SpaPODObjectBody *body, uint32_t size, uint32_t key)
|
||||
spa_pod_object_body_find_prop (const SpaPODObjectBody *body, uint32_t size, uint32_t key)
|
||||
{
|
||||
SpaPODProp *res;
|
||||
SPA_POD_OBJECT_BODY_FOREACH (body, size, res) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ extern "C" {
|
|||
#include <spa/video/raw.h>
|
||||
#include <spa/video/encoded.h>
|
||||
|
||||
typedef struct _SpaFormatVideo SpaFormatVideo;
|
||||
typedef struct _SpaVideoInfo SpaVideoInfo;
|
||||
|
||||
typedef enum {
|
||||
SPA_PROP_ID_VIDEO_INFO = SPA_PROP_ID_MEDIA_CUSTOM_START,
|
||||
|
|
@ -52,18 +52,12 @@ typedef enum {
|
|||
SPA_PROP_ID_VIDEO_ALIGNMENT,
|
||||
} SpaPropIdVideo;
|
||||
|
||||
SpaResult spa_prop_info_fill_video (SpaPropInfo *info,
|
||||
SpaPropIdVideo id,
|
||||
size_t offset);
|
||||
|
||||
SpaResult spa_format_video_init (SpaMediaType type,
|
||||
SpaMediaSubType subtype,
|
||||
SpaFormatVideo *format);
|
||||
SpaResult spa_format_video_parse (const SpaFormat *format,
|
||||
SpaFormatVideo *dest);
|
||||
SpaVideoInfo *info);
|
||||
|
||||
struct _SpaFormatVideo {
|
||||
SpaFormat format;
|
||||
struct _SpaVideoInfo {
|
||||
SpaMediaType media_type;
|
||||
SpaMediaSubType media_subtype;
|
||||
union {
|
||||
SpaVideoInfoRaw raw;
|
||||
SpaVideoInfoH264 h264;
|
||||
|
|
|
|||
|
|
@ -24,216 +24,49 @@
|
|||
|
||||
#include <spa/audio/raw.h>
|
||||
#include <spa/audio/format.h>
|
||||
#include <lib/props.h>
|
||||
|
||||
static const uint32_t format_values[] = {
|
||||
SPA_AUDIO_FORMAT_S8,
|
||||
SPA_AUDIO_FORMAT_U8,
|
||||
/* 16 bit */
|
||||
SPA_AUDIO_FORMAT_S16LE,
|
||||
SPA_AUDIO_FORMAT_S16BE,
|
||||
SPA_AUDIO_FORMAT_U16LE,
|
||||
SPA_AUDIO_FORMAT_U16BE,
|
||||
/* 24 bit in low 3 bytes of 32 bits*/
|
||||
SPA_AUDIO_FORMAT_S24_32LE,
|
||||
SPA_AUDIO_FORMAT_S24_32BE,
|
||||
SPA_AUDIO_FORMAT_U24_32LE,
|
||||
SPA_AUDIO_FORMAT_U24_32BE,
|
||||
/* 32 bit */
|
||||
SPA_AUDIO_FORMAT_S32LE,
|
||||
SPA_AUDIO_FORMAT_S32BE,
|
||||
SPA_AUDIO_FORMAT_U32LE,
|
||||
SPA_AUDIO_FORMAT_U32BE,
|
||||
/* 24 bit in 3 bytes*/
|
||||
SPA_AUDIO_FORMAT_S24LE,
|
||||
SPA_AUDIO_FORMAT_S24BE,
|
||||
SPA_AUDIO_FORMAT_U24LE,
|
||||
SPA_AUDIO_FORMAT_U24BE,
|
||||
/* 20 bit in 3 bytes*/
|
||||
SPA_AUDIO_FORMAT_S20LE,
|
||||
SPA_AUDIO_FORMAT_S20BE,
|
||||
SPA_AUDIO_FORMAT_U20LE,
|
||||
SPA_AUDIO_FORMAT_U20BE,
|
||||
/* 18 bit in 3 bytes*/
|
||||
SPA_AUDIO_FORMAT_S18LE,
|
||||
SPA_AUDIO_FORMAT_S18BE,
|
||||
SPA_AUDIO_FORMAT_U18LE,
|
||||
SPA_AUDIO_FORMAT_U18BE,
|
||||
/* float */
|
||||
SPA_AUDIO_FORMAT_F32LE,
|
||||
SPA_AUDIO_FORMAT_F32BE,
|
||||
SPA_AUDIO_FORMAT_F64LE,
|
||||
SPA_AUDIO_FORMAT_F64BE
|
||||
typedef struct {
|
||||
uint32_t key;
|
||||
uint32_t type;
|
||||
off_t offset;
|
||||
} ParseInfo;
|
||||
|
||||
static const ParseInfo raw_parse_info[] = {
|
||||
{ SPA_PROP_ID_AUDIO_INFO, SPA_POD_TYPE_BYTES, offsetof (SpaAudioInfo, info.raw) },
|
||||
{ SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.format) },
|
||||
{ SPA_PROP_ID_AUDIO_FLAGS, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.flags) },
|
||||
{ SPA_PROP_ID_AUDIO_LAYOUT, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.layout) },
|
||||
{ SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.rate) },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.channels) },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, SPA_POD_TYPE_INT, offsetof (SpaAudioInfo, info.raw.channel_mask) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo format_format_range[] = {
|
||||
{ "S8", { sizeof (uint32_t), &format_values[0] } },
|
||||
{ "U8", { sizeof (uint32_t), &format_values[1] } },
|
||||
{ "S16LE", { sizeof (uint32_t), &format_values[2] } },
|
||||
{ "S16BE", { sizeof (uint32_t), &format_values[3] } },
|
||||
{ "U16LE", { sizeof (uint32_t), &format_values[4] } },
|
||||
{ "U16BE", { sizeof (uint32_t), &format_values[5] } },
|
||||
{ "S24_32LE", { sizeof (uint32_t), &format_values[6] } },
|
||||
{ "S24_32BE", { sizeof (uint32_t), &format_values[7] } },
|
||||
{ "U24_32LE", { sizeof (uint32_t), &format_values[8] } },
|
||||
{ "U24_32BE", { sizeof (uint32_t), &format_values[9] } },
|
||||
{ "S32LE", { sizeof (uint32_t), &format_values[10] } },
|
||||
{ "S32BE", { sizeof (uint32_t), &format_values[11] } },
|
||||
{ "U32LE", { sizeof (uint32_t), &format_values[12] } },
|
||||
{ "U32BE", { sizeof (uint32_t), &format_values[13] } },
|
||||
{ "S24LE", { sizeof (uint32_t), &format_values[14] } },
|
||||
{ "S24BE", { sizeof (uint32_t), &format_values[15] } },
|
||||
{ "U24LE", { sizeof (uint32_t), &format_values[16] } },
|
||||
{ "U24BE", { sizeof (uint32_t), &format_values[17] } },
|
||||
{ "S20LE", { sizeof (uint32_t), &format_values[18] } },
|
||||
{ "S20BE", { sizeof (uint32_t), &format_values[19] } },
|
||||
{ "U20LE", { sizeof (uint32_t), &format_values[20] } },
|
||||
{ "U20BE", { sizeof (uint32_t), &format_values[21] } },
|
||||
{ "S18LE", { sizeof (uint32_t), &format_values[22] } },
|
||||
{ "S18BE", { sizeof (uint32_t), &format_values[23] } },
|
||||
{ "U18LE", { sizeof (uint32_t), &format_values[24] } },
|
||||
{ "U18BE", { sizeof (uint32_t), &format_values[25] } },
|
||||
{ "F32LE", { sizeof (uint32_t), &format_values[26] } },
|
||||
{ "F32BE", { sizeof (uint32_t), &format_values[27] } },
|
||||
{ "F64LE", { sizeof (uint32_t), &format_values[28] } },
|
||||
{ "F64BE", { sizeof (uint32_t), &format_values[29] } },
|
||||
};
|
||||
|
||||
static const uint32_t format_layouts[] = {
|
||||
SPA_AUDIO_LAYOUT_INTERLEAVED,
|
||||
SPA_AUDIO_LAYOUT_NON_INTERLEAVED,
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo layouts_range[] = {
|
||||
{ "interleaved", { sizeof (uint32_t), &format_layouts[0] } },
|
||||
{ "non-interleaved", { sizeof (uint32_t), &format_layouts[1] } },
|
||||
};
|
||||
|
||||
static const uint32_t format_flags[] = {
|
||||
SPA_AUDIO_FLAG_NONE,
|
||||
SPA_AUDIO_FLAG_UNPOSITIONED,
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo flags_range[] = {
|
||||
{ "none", { sizeof (uint32_t), &format_flags[0] } },
|
||||
{ "unpositioned", { sizeof (uint32_t), &format_flags[1] } },
|
||||
};
|
||||
|
||||
static const uint32_t min_uint32 = 1;
|
||||
static const uint32_t max_uint32 = UINT32_MAX;
|
||||
|
||||
static const SpaPropRangeInfo uint32_range[] = {
|
||||
{ "min", { sizeof (uint32_t), &min_uint32 } },
|
||||
{ "max", { sizeof (uint32_t), &max_uint32 } },
|
||||
};
|
||||
|
||||
static const SpaPropInfo format_prop_info[] =
|
||||
static const ParseInfo *
|
||||
parse_info_find (const ParseInfo *info, uint32_t key, uint32_t type)
|
||||
{
|
||||
{ SPA_PROP_ID_AUDIO_INFO, 0,
|
||||
"info",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL | SPA_PROP_FLAG_INFO,
|
||||
SPA_PROP_TYPE_POINTER, sizeof (SpaAudioInfoRaw),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_FORMAT, 0,
|
||||
"format",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_format_range), format_format_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_FLAGS, 0,
|
||||
"flags",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (flags_range), flags_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_LAYOUT, 0,
|
||||
"layout",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (layouts_range), layouts_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_RATE, 0,
|
||||
"rate",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNELS, 0,
|
||||
"channels",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_AUDIO_CHANNEL_MASK, 0,
|
||||
"channel-mask",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_BITMASK, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL },
|
||||
};
|
||||
|
||||
SpaResult
|
||||
spa_prop_info_fill_audio (SpaPropInfo *info,
|
||||
SpaPropIdAudio id,
|
||||
size_t offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (info == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
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 - sizeof (SpaFormat) + sizeof (SpaProps);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
while (info->key) {
|
||||
if (info->key == key && info->type == type)
|
||||
return info;
|
||||
info++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
SpaResult
|
||||
spa_format_audio_init (SpaMediaType type,
|
||||
SpaMediaSubType subtype,
|
||||
SpaFormatAudio *format)
|
||||
spa_format_audio_parse (const SpaFormat *format,
|
||||
SpaAudioInfo *info)
|
||||
{
|
||||
SpaPropInfo *prop_info = NULL;
|
||||
unsigned int n_prop_info = 0;
|
||||
int i;
|
||||
SpaPODProp *prop;
|
||||
const ParseInfo *pinfo, *find;
|
||||
|
||||
if (type != SPA_MEDIA_TYPE_AUDIO)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
if (format->media_type != SPA_MEDIA_TYPE_AUDIO)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
switch (subtype) {
|
||||
switch (format->media_subtype) {
|
||||
case SPA_MEDIA_SUBTYPE_RAW:
|
||||
{
|
||||
static SpaPropInfo raw_format_prop_info[] =
|
||||
{
|
||||
{ SPA_PROP_ID_AUDIO_INFO, offsetof (SpaFormatAudio, info), },
|
||||
{ SPA_PROP_ID_AUDIO_FORMAT, offsetof (SpaFormatAudio, info.raw.format), },
|
||||
{ SPA_PROP_ID_AUDIO_FLAGS, offsetof (SpaFormatAudio, info.raw.flags), },
|
||||
{ SPA_PROP_ID_AUDIO_LAYOUT, offsetof (SpaFormatAudio, info.raw.layout), },
|
||||
{ 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), },
|
||||
};
|
||||
static const SpaAudioInfoRaw default_raw_info = {
|
||||
SPA_AUDIO_FORMAT_S16,
|
||||
SPA_AUDIO_FLAG_NONE,
|
||||
SPA_AUDIO_LAYOUT_INTERLEAVED,
|
||||
44100,
|
||||
2,
|
||||
0
|
||||
};
|
||||
prop_info = raw_format_prop_info;
|
||||
n_prop_info = SPA_N_ELEMENTS (raw_format_prop_info);
|
||||
format->format.props.unset_mask = (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5);
|
||||
format->info.raw = default_raw_info;
|
||||
pinfo = raw_parse_info;
|
||||
break;
|
||||
}
|
||||
case SPA_MEDIA_SUBTYPE_MP3:
|
||||
case SPA_MEDIA_SUBTYPE_AAC:
|
||||
case SPA_MEDIA_SUBTYPE_VORBIS:
|
||||
|
|
@ -246,78 +79,21 @@ spa_format_audio_init (SpaMediaType type,
|
|||
case SPA_MEDIA_SUBTYPE_G729:
|
||||
case SPA_MEDIA_SUBTYPE_AMR:
|
||||
case SPA_MEDIA_SUBTYPE_GSM:
|
||||
break;
|
||||
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_audio (&prop_info[i],
|
||||
prop_info[i].id,
|
||||
prop_info[i].offset);
|
||||
info->media_type = format->media_type;
|
||||
info->media_subtype = format->media_subtype;
|
||||
|
||||
SPA_POD_OBJECT_BODY_FOREACH (&format->obj.body, format->obj.pod.size, prop) {
|
||||
if ((find = parse_info_find (pinfo, prop->body.key, prop->body.value.type))) {
|
||||
memcpy (SPA_MEMBER (info, find->offset, void),
|
||||
SPA_POD_BODY (&prop->body.value),
|
||||
SPA_POD_BODY_SIZE (&prop->body.value));
|
||||
}
|
||||
}
|
||||
|
||||
format->format.media_type = type;
|
||||
format->format.media_subtype = subtype;
|
||||
format->format.props.n_prop_info = n_prop_info;
|
||||
format->format.props.prop_info = prop_info;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_format_audio_parse (const SpaFormat *format,
|
||||
SpaFormatAudio *aformat)
|
||||
{
|
||||
SpaPropValue value;
|
||||
const SpaProps *props;
|
||||
SpaResult res;
|
||||
unsigned int idx;
|
||||
|
||||
if ((void *)format == (void *)aformat)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
if (format->media_type != SPA_MEDIA_TYPE_AUDIO)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
if ((res = spa_format_audio_init (format->media_type,
|
||||
format->media_subtype,
|
||||
aformat)) < 0)
|
||||
return res;
|
||||
|
||||
props = &format->props;
|
||||
idx = spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_INFO);
|
||||
if ((res = spa_props_get_value (props, idx, &value)) < 0)
|
||||
goto fallback;
|
||||
|
||||
if (props->prop_info[idx].type != SPA_PROP_TYPE_POINTER)
|
||||
goto fallback;
|
||||
|
||||
memcpy (&aformat->info, value.value, SPA_MIN (value.size, sizeof (aformat->info)));
|
||||
aformat->format.props.unset_mask = props->unset_mask;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
fallback:
|
||||
res = spa_props_copy_values (props, &aformat->format.props);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_format_audio_filter (SpaFormatAudio *format,
|
||||
const SpaFormat *filter)
|
||||
{
|
||||
SpaFormatAudio af;
|
||||
SpaResult res;
|
||||
|
||||
if (filter == NULL)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
if ((res = spa_format_audio_parse (filter, &af)) != SPA_RESULT_OK)
|
||||
return res;
|
||||
|
||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
|||
382
spa/lib/debug.c
382
spa/lib/debug.c
|
|
@ -20,9 +20,8 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "props.h"
|
||||
|
||||
struct meta_type_name {
|
||||
static const struct meta_type_name {
|
||||
const char *name;
|
||||
} meta_type_names[] = {
|
||||
{ "invalid" },
|
||||
|
|
@ -35,7 +34,7 @@ struct meta_type_name {
|
|||
};
|
||||
#define META_TYPE_NAME(t) meta_type_names[SPA_CLAMP(t,0,SPA_N_ELEMENTS(meta_type_names)-1)].name
|
||||
|
||||
struct data_type_name {
|
||||
static const struct data_type_name {
|
||||
const char *name;
|
||||
} data_type_names[] = {
|
||||
{ "invalid" },
|
||||
|
|
@ -225,19 +224,58 @@ spa_debug_dump_mem (const void *mem, size_t size)
|
|||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
struct media_type_name {
|
||||
SpaResult
|
||||
spa_debug_props (const SpaProps *props, bool print_ranges)
|
||||
{
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const char* media_audio_prop_names[] = {
|
||||
"info",
|
||||
"format",
|
||||
"flags",
|
||||
"layout",
|
||||
"rate",
|
||||
"channels",
|
||||
"channel-mask",
|
||||
};
|
||||
|
||||
static const char* media_video_prop_names[] = {
|
||||
"info",
|
||||
"format",
|
||||
"size",
|
||||
"framerate",
|
||||
"max-framerate",
|
||||
"views",
|
||||
"interlace-mode",
|
||||
"pixel-aspect-ratio",
|
||||
"multiview-mode",
|
||||
"multiview-flags",
|
||||
"chroma-site",
|
||||
"color-range",
|
||||
"color-matrix",
|
||||
"transfer-function",
|
||||
"color-primaries",
|
||||
"profile",
|
||||
"stream-format",
|
||||
"alignment",
|
||||
};
|
||||
|
||||
static const struct media_type_name {
|
||||
const char *name;
|
||||
unsigned int first;
|
||||
unsigned int last;
|
||||
unsigned int idx;
|
||||
const char **prop_names;
|
||||
} media_type_names[] = {
|
||||
{ "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 },
|
||||
{ "audio", SPA_MEDIA_SUBTYPE_AUDIO_FIRST, SPA_MEDIA_SUBTYPE_AUDIO_LAST, 16, media_audio_prop_names },
|
||||
{ "video", SPA_MEDIA_SUBTYPE_VIDEO_FIRST, SPA_MEDIA_SUBTYPE_VIDEO_LAST, 2, media_video_prop_names },
|
||||
{ "image", 0, 0 },
|
||||
};
|
||||
|
||||
struct media_subtype_name {
|
||||
|
||||
static const struct media_subtype_name {
|
||||
const char *name;
|
||||
} media_subtype_names[] = {
|
||||
{ "invalid" },
|
||||
|
|
@ -273,222 +311,184 @@ struct media_subtype_name {
|
|||
{ "gsm" },
|
||||
};
|
||||
|
||||
struct prop_type_name {
|
||||
struct pod_type_name {
|
||||
const char *name;
|
||||
const char *CCName;
|
||||
} prop_type_names[] = {
|
||||
} pod_type_names[] = {
|
||||
{ "invalid", "*Invalid*" },
|
||||
{ "bool", "Boolean" },
|
||||
{ "int8", "Int8" },
|
||||
{ "uint8", "UInt8" },
|
||||
{ "int16", "Int16" },
|
||||
{ "uint16", "UInt16" },
|
||||
{ "int32", "Int32" },
|
||||
{ "uint32", "UInt32" },
|
||||
{ "int64", "Int64" },
|
||||
{ "uint64", "UInt64" },
|
||||
{ "bool", "Bool" },
|
||||
{ "int", "Int" },
|
||||
{ "uint", "UInt" },
|
||||
{ "long", "Long" },
|
||||
{ "float", "Float" },
|
||||
{ "double", "Double" },
|
||||
{ "string", "String" },
|
||||
{ "rectangle", "Rectangle" },
|
||||
{ "fraction", "Fraction" },
|
||||
{ "bitmask", "Bitmask" },
|
||||
{ "pointer", "Pointer" },
|
||||
{ "array", "Array" },
|
||||
{ "struct", "Struct" },
|
||||
{ "object", "Object" },
|
||||
{ "prop", "Prop" },
|
||||
{ "bytes", "Bytes" },
|
||||
};
|
||||
|
||||
static void
|
||||
print_value (const SpaPropInfo *info, const SpaPropValue *val)
|
||||
print_pod_value (uint32_t size, uint32_t type, void *body, int prefix)
|
||||
{
|
||||
SpaPropType type = info->type;
|
||||
bool enum_string = false;
|
||||
const void *enum_value;
|
||||
switch (type) {
|
||||
case SPA_POD_TYPE_BOOL:
|
||||
printf ("%-*sBool %d\n", prefix, "", *(int32_t *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_INT:
|
||||
printf ("%-*sInt %d\n", prefix, "", *(int32_t *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_LONG:
|
||||
printf ("%-*sLong %"PRIi64"\n", prefix, "", *(int64_t *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_FLOAT:
|
||||
printf ("%-*sFloat %f\n", prefix, "", *(float *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_DOUBLE:
|
||||
printf ("%-*sDouble %g\n", prefix, "", *(double *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_STRING:
|
||||
printf ("%-*sString %s\n", prefix, "", (char *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_RECTANGLE:
|
||||
{
|
||||
SpaRectangle *r = body;
|
||||
printf ("%-*sRectangle %dx%d\n", prefix, "", r->width, r->height);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_FRACTION:
|
||||
{
|
||||
SpaFraction *f = body;
|
||||
printf ("%-*sFraction %d/%d\n", prefix, "", f->num, f->denom);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_BITMASK:
|
||||
printf ("%-*sBitmask\n", prefix, "");
|
||||
break;
|
||||
case SPA_POD_TYPE_ARRAY:
|
||||
{
|
||||
SpaPODArrayBody *b = body;
|
||||
void *p;
|
||||
printf ("%-*sArray: child.size %d, child.type %d\n", prefix, "", b->child.size, b->child.type);
|
||||
|
||||
if (info->range_type == SPA_PROP_RANGE_TYPE_ENUM) {
|
||||
SPA_POD_ARRAY_BODY_FOREACH (b, size, p)
|
||||
print_pod_value (b->child.size, b->child.type, p, prefix + 2);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_STRUCT:
|
||||
{
|
||||
SpaPOD *b = body, *p;
|
||||
printf ("%-*sStruct: size %d\n", prefix, "", size);
|
||||
SPA_POD_STRUCT_BODY_FOREACH (b, size, p)
|
||||
print_pod_value (p->size, p->type, SPA_POD_BODY (p), prefix + 2);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_OBJECT:
|
||||
{
|
||||
SpaPODObjectBody *b = body;
|
||||
SpaPODProp *p;
|
||||
void *alt;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < info->n_range_values; i++) {
|
||||
if (memcmp (info->range_values[i].val.value, val->value, val->size) == 0) {
|
||||
if (info->range_values[i].name) {
|
||||
enum_value = info->range_values[i].name;
|
||||
enum_string = true;
|
||||
printf ("%-*sObject: size %d\n", prefix, "", size);
|
||||
SPA_POD_OBJECT_BODY_FOREACH (b, size, p) {
|
||||
printf ("%-*sProp: key %d, flags %d\n", prefix + 2, "", p->body.key, p->body.flags);
|
||||
if (p->body.flags & SPA_POD_PROP_FLAG_UNSET)
|
||||
printf ("%-*sUnset (Default):\n", prefix + 4, "");
|
||||
else
|
||||
printf ("%-*sValue:\n", prefix + 4, "");
|
||||
print_pod_value (p->body.value.size, p->body.value.type, SPA_POD_BODY (&p->body.value), prefix + 6);
|
||||
|
||||
i = 0;
|
||||
SPA_POD_PROP_ALTERNATIVE_FOREACH (&p->body, p->pod.size, alt) {
|
||||
if (i == 0)
|
||||
printf ("%-*sAlternatives:\n", prefix + 4, "");
|
||||
print_pod_value (p->body.value.size, p->body.value.type, alt, prefix + 6);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SPA_PROP_TYPE_INVALID:
|
||||
fprintf (stderr, "invalid");
|
||||
break;
|
||||
case SPA_PROP_TYPE_BOOL:
|
||||
fprintf (stderr, "%s", *(bool *)val->value ? "true" : "false");
|
||||
break;
|
||||
case SPA_PROP_TYPE_INT8:
|
||||
fprintf (stderr, "%" PRIi8, *(int8_t *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_UINT8:
|
||||
fprintf (stderr, "%" PRIu8, *(uint8_t *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_INT16:
|
||||
fprintf (stderr, "%" PRIi16, *(int16_t *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_UINT16:
|
||||
fprintf (stderr, "%" PRIu16, *(uint16_t *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_INT32:
|
||||
fprintf (stderr, "%" PRIi32, *(int32_t *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_UINT32:
|
||||
fprintf (stderr, "%" PRIu32, *(uint32_t *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_INT64:
|
||||
fprintf (stderr, "%" PRIi64 "\n", *(int64_t *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_UINT64:
|
||||
fprintf (stderr, "%" PRIu64 "\n", *(uint64_t *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_INT:
|
||||
fprintf (stderr, "%d", *(int *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_UINT:
|
||||
fprintf (stderr, "%u", *(unsigned int *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_FLOAT:
|
||||
fprintf (stderr, "%f", *(float *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_DOUBLE:
|
||||
fprintf (stderr, "%g", *(double *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_STRING:
|
||||
fprintf (stderr, "\"%s\"", (char *)val->value);
|
||||
break;
|
||||
case SPA_PROP_TYPE_RECTANGLE:
|
||||
|
||||
SpaResult
|
||||
spa_debug_pod (const SpaPOD *pod)
|
||||
{
|
||||
const SpaRectangle *r = val->value;
|
||||
print_pod_value (pod->size, pod->type, SPA_POD_BODY (pod), 0);
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
print_format_value (uint32_t size, uint32_t type, void *body)
|
||||
{
|
||||
switch (type) {
|
||||
case SPA_POD_TYPE_BOOL:
|
||||
fprintf (stderr, "%s", *(int32_t *) body ? "true" : "false");
|
||||
break;
|
||||
case SPA_POD_TYPE_INT:
|
||||
fprintf (stderr, "%"PRIi32, *(int32_t *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_LONG:
|
||||
fprintf (stderr, "%"PRIi64, *(int64_t *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_FLOAT:
|
||||
fprintf (stderr, "%f", *(float *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_DOUBLE:
|
||||
fprintf (stderr, "%g", *(double *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_STRING:
|
||||
fprintf (stderr, "%s", (char *) body);
|
||||
break;
|
||||
case SPA_POD_TYPE_RECTANGLE:
|
||||
{
|
||||
SpaRectangle *r = body;
|
||||
fprintf (stderr, "%"PRIu32"x%"PRIu32, r->width, r->height);
|
||||
break;
|
||||
}
|
||||
case SPA_PROP_TYPE_FRACTION:
|
||||
case SPA_POD_TYPE_FRACTION:
|
||||
{
|
||||
const SpaFraction *f = val->value;
|
||||
SpaFraction *f = body;
|
||||
fprintf (stderr, "%"PRIu32"/%"PRIu32, f->num, f->denom);
|
||||
break;
|
||||
}
|
||||
case SPA_PROP_TYPE_BITMASK:
|
||||
break;
|
||||
case SPA_PROP_TYPE_POINTER:
|
||||
fprintf (stderr, "%p", val->value);
|
||||
case SPA_POD_TYPE_BITMASK:
|
||||
fprintf (stderr, "Bitmask");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (enum_string)
|
||||
fprintf (stderr, " (%s)", (char *)enum_value);
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_debug_props (const SpaProps *props, bool print_ranges)
|
||||
{
|
||||
SpaResult res;
|
||||
const SpaPropInfo *info;
|
||||
int i, j;
|
||||
|
||||
if (props == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
fprintf (stderr, "Properties (%d items):\n", props->n_prop_info);
|
||||
for (i = 0; i < props->n_prop_info; i++) {
|
||||
SpaPropValue value;
|
||||
|
||||
info = &props->prop_info[i];
|
||||
|
||||
fprintf (stderr, " %-20s flags: ", info->name);
|
||||
if (info->flags & SPA_PROP_FLAG_READABLE)
|
||||
fprintf (stderr, "readable ");
|
||||
if (info->flags & SPA_PROP_FLAG_WRITABLE)
|
||||
fprintf (stderr, "writable ");
|
||||
if (info->flags & SPA_PROP_FLAG_OPTIONAL)
|
||||
fprintf (stderr, "optional ");
|
||||
if (info->flags & SPA_PROP_FLAG_DEPRECATED)
|
||||
fprintf (stderr, "deprecated ");
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
fprintf (stderr, "%-23.23s %s. ", "", prop_type_names[info->type].CCName);
|
||||
|
||||
res = spa_props_get_value (props, i, &value);
|
||||
|
||||
fprintf (stderr, "Current: ");
|
||||
if (res == SPA_RESULT_OK)
|
||||
print_value (info, &value);
|
||||
else if (res == SPA_RESULT_PROPERTY_UNSET)
|
||||
fprintf (stderr, "Unset");
|
||||
else
|
||||
fprintf (stderr, "Error %d", res);
|
||||
fprintf (stderr, ".\n");
|
||||
|
||||
if (!print_ranges)
|
||||
continue;
|
||||
|
||||
if (info->range_type != SPA_PROP_RANGE_TYPE_NONE) {
|
||||
fprintf (stderr, "%-23.23s ", "");
|
||||
switch (info->range_type) {
|
||||
case SPA_PROP_RANGE_TYPE_MIN_MAX:
|
||||
fprintf (stderr, "Range");
|
||||
break;
|
||||
case SPA_PROP_RANGE_TYPE_STEP:
|
||||
fprintf (stderr, "Step");
|
||||
break;
|
||||
case SPA_PROP_RANGE_TYPE_ENUM:
|
||||
fprintf (stderr, "Enum");
|
||||
break;
|
||||
case SPA_PROP_RANGE_TYPE_FLAGS:
|
||||
fprintf (stderr, "Flags");
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unknown");
|
||||
break;
|
||||
}
|
||||
fprintf (stderr, ".\n");
|
||||
|
||||
for (j = 0; j < info->n_range_values; j++) {
|
||||
const SpaPropRangeInfo *rinfo = &info->range_values[j];
|
||||
fprintf (stderr, "%-23.23s ", "");
|
||||
print_value (info, &rinfo->val);
|
||||
fprintf (stderr, "\t: %-12s\n", rinfo->name);
|
||||
}
|
||||
}
|
||||
if (info->extra) {
|
||||
fprintf (stderr, "Extra info: \n");
|
||||
spa_debug_dict (info->extra);
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_debug_format (const SpaFormat *format)
|
||||
{
|
||||
const SpaProps *props;
|
||||
int i, first, last, idx;
|
||||
const char *media_type;
|
||||
const char *media_subtype;
|
||||
const char **prop_names;
|
||||
SpaPODProp *prop;
|
||||
|
||||
if (format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
props = &format->props;
|
||||
|
||||
if (format->media_type > 0 && format->media_type < SPA_N_ELEMENTS (media_type_names)) {
|
||||
media_type = media_type_names[format->media_type].name;
|
||||
first = media_type_names[format->media_type].first;
|
||||
last = media_type_names[format->media_type].last;
|
||||
idx = media_type_names[format->media_type].idx;
|
||||
prop_names = media_type_names[format->media_type].prop_names;
|
||||
}
|
||||
else {
|
||||
media_type = "unknown";
|
||||
idx = first = last = -1;
|
||||
prop_names = NULL;
|
||||
}
|
||||
|
||||
if (format->media_subtype >= SPA_MEDIA_SUBTYPE_ANY_FIRST &&
|
||||
|
|
@ -501,35 +501,28 @@ spa_debug_format (const SpaFormat *format)
|
|||
|
||||
fprintf (stderr, "%-6s %s/%s\n", "", media_type, media_subtype);
|
||||
|
||||
for (i = 0; i < props->n_prop_info; i++) {
|
||||
const SpaPropInfo *info = &props->prop_info[i];
|
||||
SpaPropValue value;
|
||||
SpaResult res;
|
||||
|
||||
res = spa_props_get_value (props, i, &value);
|
||||
|
||||
if (info->flags & SPA_PROP_FLAG_INFO)
|
||||
continue;
|
||||
if (res == SPA_RESULT_PROPERTY_UNSET && info->flags & SPA_PROP_FLAG_OPTIONAL)
|
||||
SPA_POD_OBJECT_BODY_FOREACH (&format->obj.body, format->obj.pod.size, prop) {
|
||||
if ((prop->body.flags & SPA_POD_PROP_FLAG_UNSET) &&
|
||||
(prop->body.flags & SPA_POD_PROP_FLAG_OPTIONAL))
|
||||
continue;
|
||||
|
||||
fprintf (stderr, " %20s : (%s) ", info->name, prop_type_names[info->type].name);
|
||||
if (res == SPA_RESULT_OK) {
|
||||
print_value (info, &value);
|
||||
} else if (res == SPA_RESULT_PROPERTY_UNSET) {
|
||||
int j;
|
||||
fprintf (stderr, " %20s : (%s) ", prop_names[prop->body.key - SPA_PROP_ID_MEDIA_CUSTOM_START], pod_type_names[prop->body.value.type].name);
|
||||
if (!(prop->body.flags & SPA_POD_PROP_FLAG_UNSET)) {
|
||||
print_format_value (prop->body.value.size, prop->body.value.type, SPA_POD_BODY (&prop->body.value));
|
||||
} else {
|
||||
const char *ssep, *esep, *sep;
|
||||
void *alt;
|
||||
|
||||
switch (info->range_type) {
|
||||
case SPA_PROP_RANGE_TYPE_MIN_MAX:
|
||||
case SPA_PROP_RANGE_TYPE_STEP:
|
||||
switch (prop->body.flags & SPA_POD_PROP_RANGE_MASK) {
|
||||
case SPA_POD_PROP_RANGE_MIN_MAX:
|
||||
case SPA_POD_PROP_RANGE_STEP:
|
||||
ssep = "[ ";
|
||||
sep = ", ";
|
||||
esep = " ]";
|
||||
break;
|
||||
default:
|
||||
case SPA_PROP_RANGE_TYPE_ENUM:
|
||||
case SPA_PROP_RANGE_TYPE_FLAGS:
|
||||
case SPA_POD_PROP_RANGE_ENUM:
|
||||
case SPA_POD_PROP_RANGE_FLAGS:
|
||||
ssep = "{ ";
|
||||
sep = ", ";
|
||||
esep = " }";
|
||||
|
|
@ -537,14 +530,15 @@ spa_debug_format (const SpaFormat *format)
|
|||
}
|
||||
|
||||
fprintf (stderr, ssep);
|
||||
for (j = 0; j < info->n_range_values; j++) {
|
||||
const SpaPropRangeInfo *rinfo = &info->range_values[j];
|
||||
print_value (info, &rinfo->val);
|
||||
fprintf (stderr, "%s", j + 1 < info->n_range_values ? sep : "");
|
||||
|
||||
i = 0;
|
||||
SPA_POD_PROP_ALTERNATIVE_FOREACH (&prop->body, prop->pod.size, alt) {
|
||||
if (i > 0)
|
||||
fprintf (stderr, "%s", sep);
|
||||
print_format_value (prop->body.value.size, prop->body.value.type, alt);
|
||||
i++;
|
||||
}
|
||||
fprintf (stderr, esep);
|
||||
} else {
|
||||
fprintf (stderr, "*Error*");
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,12 +27,14 @@ extern "C" {
|
|||
#include <spa/defs.h>
|
||||
#include <spa/port.h>
|
||||
#include <spa/buffer.h>
|
||||
#include <spa/pod.h>
|
||||
#include <spa/props.h>
|
||||
#include <spa/format.h>
|
||||
#include <spa/dict.h>
|
||||
|
||||
SpaResult spa_debug_port_info (const SpaPortInfo *info);
|
||||
SpaResult spa_debug_buffer (const SpaBuffer *buffer);
|
||||
SpaResult spa_debug_pod (const SpaPOD *pod);
|
||||
SpaResult spa_debug_props (const SpaProps *props, bool print_ranges);
|
||||
SpaResult spa_debug_format (const SpaFormat *format);
|
||||
SpaResult spa_debug_dump_mem (const void *data, size_t size);
|
||||
|
|
|
|||
|
|
@ -24,551 +24,80 @@
|
|||
|
||||
#include <spa/video/raw.h>
|
||||
#include <spa/video/format.h>
|
||||
#include <spa/format-builder.h>
|
||||
|
||||
#include "video-raw.h"
|
||||
#include "props.h"
|
||||
typedef struct {
|
||||
uint32_t key;
|
||||
uint32_t type;
|
||||
off_t offset;
|
||||
} ParseInfo;
|
||||
|
||||
static const uint32_t format_values[] = {
|
||||
SPA_VIDEO_FORMAT_UNKNOWN,
|
||||
SPA_VIDEO_FORMAT_ENCODED,
|
||||
SPA_VIDEO_FORMAT_I420,
|
||||
SPA_VIDEO_FORMAT_YV12,
|
||||
SPA_VIDEO_FORMAT_YUY2,
|
||||
SPA_VIDEO_FORMAT_UYVY,
|
||||
SPA_VIDEO_FORMAT_AYUV,
|
||||
SPA_VIDEO_FORMAT_RGBx,
|
||||
SPA_VIDEO_FORMAT_BGRx,
|
||||
SPA_VIDEO_FORMAT_xRGB,
|
||||
SPA_VIDEO_FORMAT_xBGR,
|
||||
SPA_VIDEO_FORMAT_RGBA,
|
||||
SPA_VIDEO_FORMAT_BGRA,
|
||||
SPA_VIDEO_FORMAT_ARGB,
|
||||
SPA_VIDEO_FORMAT_ABGR,
|
||||
SPA_VIDEO_FORMAT_RGB,
|
||||
SPA_VIDEO_FORMAT_BGR,
|
||||
SPA_VIDEO_FORMAT_Y41B,
|
||||
SPA_VIDEO_FORMAT_Y42B,
|
||||
SPA_VIDEO_FORMAT_YVYU,
|
||||
SPA_VIDEO_FORMAT_Y444,
|
||||
SPA_VIDEO_FORMAT_v210,
|
||||
SPA_VIDEO_FORMAT_v216,
|
||||
SPA_VIDEO_FORMAT_NV12,
|
||||
SPA_VIDEO_FORMAT_NV21,
|
||||
SPA_VIDEO_FORMAT_GRAY8,
|
||||
SPA_VIDEO_FORMAT_GRAY16_BE,
|
||||
SPA_VIDEO_FORMAT_GRAY16_LE,
|
||||
SPA_VIDEO_FORMAT_v308,
|
||||
SPA_VIDEO_FORMAT_RGB16,
|
||||
SPA_VIDEO_FORMAT_BGR16,
|
||||
SPA_VIDEO_FORMAT_RGB15,
|
||||
SPA_VIDEO_FORMAT_BGR15,
|
||||
SPA_VIDEO_FORMAT_UYVP,
|
||||
SPA_VIDEO_FORMAT_A420,
|
||||
SPA_VIDEO_FORMAT_RGB8P,
|
||||
SPA_VIDEO_FORMAT_YUV9,
|
||||
SPA_VIDEO_FORMAT_YVU9,
|
||||
SPA_VIDEO_FORMAT_IYU1,
|
||||
SPA_VIDEO_FORMAT_ARGB64,
|
||||
SPA_VIDEO_FORMAT_AYUV64,
|
||||
SPA_VIDEO_FORMAT_r210,
|
||||
SPA_VIDEO_FORMAT_I420_10BE,
|
||||
SPA_VIDEO_FORMAT_I420_10LE,
|
||||
SPA_VIDEO_FORMAT_I422_10BE,
|
||||
SPA_VIDEO_FORMAT_I422_10LE,
|
||||
SPA_VIDEO_FORMAT_Y444_10BE,
|
||||
SPA_VIDEO_FORMAT_Y444_10LE,
|
||||
SPA_VIDEO_FORMAT_GBR,
|
||||
SPA_VIDEO_FORMAT_GBR_10BE,
|
||||
SPA_VIDEO_FORMAT_GBR_10LE,
|
||||
SPA_VIDEO_FORMAT_NV16,
|
||||
SPA_VIDEO_FORMAT_NV24,
|
||||
SPA_VIDEO_FORMAT_NV12_64Z32,
|
||||
SPA_VIDEO_FORMAT_A420_10BE,
|
||||
SPA_VIDEO_FORMAT_A420_10LE,
|
||||
SPA_VIDEO_FORMAT_A422_10BE,
|
||||
SPA_VIDEO_FORMAT_A422_10LE,
|
||||
SPA_VIDEO_FORMAT_A444_10BE,
|
||||
SPA_VIDEO_FORMAT_A444_10LE,
|
||||
SPA_VIDEO_FORMAT_NV61,
|
||||
SPA_VIDEO_FORMAT_P010_10BE,
|
||||
SPA_VIDEO_FORMAT_P010_10LE,
|
||||
SPA_VIDEO_FORMAT_IYU2,
|
||||
static const ParseInfo raw_parse_info[] = {
|
||||
{ SPA_PROP_ID_VIDEO_INFO, SPA_POD_TYPE_BYTES, offsetof (SpaVideoInfo, info.raw) },
|
||||
{ SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.format) },
|
||||
{ SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, offsetof (SpaVideoInfo, info.raw.size) },
|
||||
{ SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.raw.framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.raw.max_framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_VIEWS, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.views) },
|
||||
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.interlace_mode) },
|
||||
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.raw.pixel_aspect_ratio) },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.multiview_mode) },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.multiview_flags) },
|
||||
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.chroma_site) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.color_range) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.color_matrix) },
|
||||
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.transfer_function) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, SPA_POD_TYPE_INT, offsetof (SpaVideoInfo, info.raw.color_primaries) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo format_range[] = {
|
||||
{ "UNKNOWN", { sizeof (uint32_t), &format_values[0] } },
|
||||
{ "ENCODED", { sizeof (uint32_t), &format_values[1] } },
|
||||
{ "I420", { sizeof (uint32_t), &format_values[2] } },
|
||||
{ "YV12", { sizeof (uint32_t), &format_values[3] } },
|
||||
{ "YUY2", { sizeof (uint32_t), &format_values[4] } },
|
||||
{ "UYVY", { sizeof (uint32_t), &format_values[5] } },
|
||||
{ "AYUV", { sizeof (uint32_t), &format_values[6] } },
|
||||
{ "RGBx", { sizeof (uint32_t), &format_values[7] } },
|
||||
{ "BGRx", { sizeof (uint32_t), &format_values[8] } },
|
||||
{ "xRGB", { sizeof (uint32_t), &format_values[9] } },
|
||||
{ "xBGR", { sizeof (uint32_t), &format_values[10] } },
|
||||
{ "RGBA", { sizeof (uint32_t), &format_values[11] } },
|
||||
{ "BGRA", { sizeof (uint32_t), &format_values[12] } },
|
||||
{ "ARGB", { sizeof (uint32_t), &format_values[13] } },
|
||||
{ "ABGR", { sizeof (uint32_t), &format_values[14] } },
|
||||
{ "RGB", { sizeof (uint32_t), &format_values[15] } },
|
||||
{ "BGR", { sizeof (uint32_t), &format_values[16] } },
|
||||
{ "Y41B", { sizeof (uint32_t), &format_values[17] } },
|
||||
{ "Y42B", { sizeof (uint32_t), &format_values[18] } },
|
||||
{ "YVYU", { sizeof (uint32_t), &format_values[19] } },
|
||||
{ "Y444", { sizeof (uint32_t), &format_values[20] } },
|
||||
{ "v210", { sizeof (uint32_t), &format_values[21] } },
|
||||
{ "v216", { sizeof (uint32_t), &format_values[22] } },
|
||||
{ "NV12", { sizeof (uint32_t), &format_values[23] } },
|
||||
{ "NV21", { sizeof (uint32_t), &format_values[24] } },
|
||||
{ "GRAY8", { sizeof (uint32_t), &format_values[25] } },
|
||||
{ "GRAY16_BE", { sizeof (uint32_t), &format_values[26] } },
|
||||
{ "GRAY16_LE", { sizeof (uint32_t), &format_values[27] } },
|
||||
{ "v308", { sizeof (uint32_t), &format_values[28] } },
|
||||
{ "RGB16", { sizeof (uint32_t), &format_values[29] } },
|
||||
{ "BGR16", { sizeof (uint32_t), &format_values[30] } },
|
||||
{ "RGB15", { sizeof (uint32_t), &format_values[31] } },
|
||||
{ "BGR15", { sizeof (uint32_t), &format_values[32] } },
|
||||
{ "UYVP", { sizeof (uint32_t), &format_values[33] } },
|
||||
{ "A420", { sizeof (uint32_t), &format_values[34] } },
|
||||
{ "RGB8P", { sizeof (uint32_t), &format_values[35] } },
|
||||
{ "YUV9", { sizeof (uint32_t), &format_values[36] } },
|
||||
{ "YVU9", { sizeof (uint32_t), &format_values[37] } },
|
||||
{ "IYU1", { sizeof (uint32_t), &format_values[38] } },
|
||||
{ "ARGB64", { sizeof (uint32_t), &format_values[39] } },
|
||||
{ "AYUV64", { sizeof (uint32_t), &format_values[40] } },
|
||||
{ "r210", { sizeof (uint32_t), &format_values[41] } },
|
||||
{ "I420_10BE", { sizeof (uint32_t), &format_values[42] } },
|
||||
{ "I420_10LE", { sizeof (uint32_t), &format_values[43] } },
|
||||
{ "I422_10BE", { sizeof (uint32_t), &format_values[44] } },
|
||||
{ "I422_10LE", { sizeof (uint32_t), &format_values[45] } },
|
||||
{ "I444_10BE", { sizeof (uint32_t), &format_values[46] } },
|
||||
{ "I444_10LE", { sizeof (uint32_t), &format_values[47] } },
|
||||
{ "GBR", { sizeof (uint32_t), &format_values[48] } },
|
||||
{ "GBR_10BE", { sizeof (uint32_t), &format_values[49] } },
|
||||
{ "GBR_10LE", { sizeof (uint32_t), &format_values[50] } },
|
||||
{ "NV16", { sizeof (uint32_t), &format_values[51] } },
|
||||
{ "NV24", { sizeof (uint32_t), &format_values[52] } },
|
||||
{ "NV12_64Z32", { sizeof (uint32_t), &format_values[53] } },
|
||||
{ "A420_10BE", { sizeof (uint32_t), &format_values[54] } },
|
||||
{ "A420_10LE", { sizeof (uint32_t), &format_values[55] } },
|
||||
{ "A422_10BE", { sizeof (uint32_t), &format_values[56] } },
|
||||
{ "A422_10LE", { sizeof (uint32_t), &format_values[57] } },
|
||||
{ "A444_10BE", { sizeof (uint32_t), &format_values[58] } },
|
||||
{ "A444_10LE", { sizeof (uint32_t), &format_values[59] } },
|
||||
{ "NV61", { sizeof (uint32_t), &format_values[60] } },
|
||||
{ "P010_10BE", { sizeof (uint32_t), &format_values[61] } },
|
||||
{ "P010_10LE", { sizeof (uint32_t), &format_values[62] } },
|
||||
{ "IYU2", { sizeof (uint32_t), &format_values[63] } },
|
||||
static const ParseInfo h264_parse_info[] = {
|
||||
{ SPA_PROP_ID_VIDEO_INFO, SPA_POD_TYPE_BYTES, offsetof (SpaVideoInfo, info.h264) },
|
||||
{ SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, offsetof (SpaVideoInfo, info.h264.size) },
|
||||
{ SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.h264.framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.h264.max_framerate) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
static const SpaRectangle min_size = { 1, 1 };
|
||||
static const SpaRectangle max_size = { UINT32_MAX, UINT32_MAX };
|
||||
|
||||
static const SpaPropRangeInfo size_range[] = {
|
||||
{ "min", { sizeof (SpaRectangle), &min_size } },
|
||||
{ "max", { sizeof (SpaRectangle), &max_size } },
|
||||
static const ParseInfo mjpg_parse_info[] = {
|
||||
{ SPA_PROP_ID_VIDEO_INFO, SPA_POD_TYPE_BYTES, offsetof (SpaVideoInfo, info.h264) },
|
||||
{ SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE, offsetof (SpaVideoInfo, info.h264.size) },
|
||||
{ SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.h264.framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, SPA_POD_TYPE_FRACTION, offsetof (SpaVideoInfo, info.h264.max_framerate) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
static const uint32_t interlace_modes[] = {
|
||||
SPA_VIDEO_INTERLACE_MODE_PROGRESSIVE,
|
||||
SPA_VIDEO_INTERLACE_MODE_INTERLEAVED,
|
||||
SPA_VIDEO_INTERLACE_MODE_MIXED,
|
||||
SPA_VIDEO_INTERLACE_MODE_FIELDS
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo interlace_mode_range[] = {
|
||||
{ "progressive", { sizeof (uint32_t), &interlace_modes[0] } },
|
||||
{ "interleaved", { sizeof (uint32_t), &interlace_modes[1] } },
|
||||
{ "mixed", { sizeof (uint32_t), &interlace_modes[2] } },
|
||||
{ "fields", { sizeof (uint32_t), &interlace_modes[3] } },
|
||||
};
|
||||
|
||||
|
||||
static const uint32_t multiview_modes[] = {
|
||||
SPA_VIDEO_MULTIVIEW_MODE_NONE,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_MONO,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_LEFT,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_RIGHT,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_CHECKERBOARD,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME,
|
||||
SPA_VIDEO_MULTIVIEW_MODE_SEPARATED
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo multiview_mode_range[] = {
|
||||
{ "unknown", { sizeof (uint32_t), &multiview_modes[0] } },
|
||||
{ "mono", { sizeof (uint32_t), &multiview_modes[1] } },
|
||||
{ "left", { sizeof (uint32_t), &multiview_modes[2] } },
|
||||
{ "right", { sizeof (uint32_t), &multiview_modes[3] } },
|
||||
{ "side-by-side", { sizeof (uint32_t), &multiview_modes[4] } },
|
||||
{ "side-by-side-quincunx", { sizeof (uint32_t), &multiview_modes[5] } },
|
||||
{ "column-interleaved", { sizeof (uint32_t), &multiview_modes[6] } },
|
||||
{ "row-interleaved", { sizeof (uint32_t), &multiview_modes[7] } },
|
||||
{ "top-bottom", { sizeof (uint32_t), &multiview_modes[8] } },
|
||||
{ "checkerboard", { sizeof (uint32_t), &multiview_modes[9] } },
|
||||
{ "frame-by-frame", { sizeof (uint32_t), &multiview_modes[10] } },
|
||||
{ "multiview-frame-by-frame", { sizeof (uint32_t), &multiview_modes[11] } },
|
||||
{ "separated", { sizeof (uint32_t), &multiview_modes[12] } },
|
||||
};
|
||||
|
||||
static const uint32_t multiview_flags[] = {
|
||||
SPA_VIDEO_MULTIVIEW_FLAGS_NONE,
|
||||
SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST,
|
||||
SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED,
|
||||
SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED,
|
||||
SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED,
|
||||
SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED,
|
||||
SPA_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT,
|
||||
SPA_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO,
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo multiview_flags_range[] = {
|
||||
{ "none", { sizeof (uint32_t), &multiview_flags[0] } },
|
||||
{ "right-view-first", { sizeof (uint32_t), &multiview_flags[1] } },
|
||||
{ "left-flipped", { sizeof (uint32_t), &multiview_flags[2] } },
|
||||
{ "left-flopped", { sizeof (uint32_t), &multiview_flags[3] } },
|
||||
{ "right-flipped", { sizeof (uint32_t), &multiview_flags[4] } },
|
||||
{ "right-flopped", { sizeof (uint32_t), &multiview_flags[5] } },
|
||||
{ "half-aspect", { sizeof (uint32_t), &multiview_flags[6] } },
|
||||
{ "mixed-mono", { sizeof (uint32_t), &multiview_flags[7] } },
|
||||
};
|
||||
|
||||
static const uint32_t chroma_sites[] = {
|
||||
SPA_VIDEO_CHROMA_SITE_UNKNOWN,
|
||||
SPA_VIDEO_CHROMA_SITE_NONE,
|
||||
SPA_VIDEO_CHROMA_SITE_H_COSITED,
|
||||
SPA_VIDEO_CHROMA_SITE_V_COSITED,
|
||||
SPA_VIDEO_CHROMA_SITE_ALT_LINE,
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo chroma_site_range[] = {
|
||||
{ "unknown", { sizeof (uint32_t), &chroma_sites[0] } },
|
||||
{ "none", { sizeof (uint32_t), &chroma_sites[1] } },
|
||||
{ "h-cosited", { sizeof (uint32_t), &chroma_sites[2] } },
|
||||
{ "v-cosited", { sizeof (uint32_t), &chroma_sites[3] } },
|
||||
{ "alt-line", { sizeof (uint32_t), &chroma_sites[4] } }
|
||||
};
|
||||
|
||||
static const uint32_t color_ranges[] = {
|
||||
SPA_VIDEO_COLOR_RANGE_UNKNOWN,
|
||||
SPA_VIDEO_COLOR_RANGE_0_255,
|
||||
SPA_VIDEO_COLOR_RANGE_16_235
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo color_range_range[] = {
|
||||
{ "unknown", { sizeof (uint32_t), &color_ranges[0] } },
|
||||
{ "0_255", { sizeof (uint32_t), &color_ranges[1] } },
|
||||
{ "16_235", { sizeof (uint32_t), &color_ranges[2] } },
|
||||
};
|
||||
|
||||
static const uint32_t color_matrices[] = {
|
||||
SPA_VIDEO_COLOR_MATRIX_UNKNOWN,
|
||||
SPA_VIDEO_COLOR_MATRIX_RGB,
|
||||
SPA_VIDEO_COLOR_MATRIX_FCC,
|
||||
SPA_VIDEO_COLOR_MATRIX_BT709,
|
||||
SPA_VIDEO_COLOR_MATRIX_BT601,
|
||||
SPA_VIDEO_COLOR_MATRIX_SMPTE240M,
|
||||
SPA_VIDEO_COLOR_MATRIX_BT2020
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo color_matrix_range[] = {
|
||||
{ "unknown", { sizeof (uint32_t), &color_matrices[0] } },
|
||||
{ "rgb", { sizeof (uint32_t), &color_matrices[1] } },
|
||||
{ "fcc", { sizeof (uint32_t), &color_matrices[2] } },
|
||||
{ "bt709", { sizeof (uint32_t), &color_matrices[3] } },
|
||||
{ "bt601", { sizeof (uint32_t), &color_matrices[4] } },
|
||||
{ "smpte240m", { sizeof (uint32_t), &color_matrices[5] } },
|
||||
{ "bt2020", { sizeof (uint32_t), &color_matrices[6] } },
|
||||
};
|
||||
|
||||
static const uint32_t transfer_functions[] = {
|
||||
SPA_VIDEO_TRANSFER_UNKNOWN,
|
||||
SPA_VIDEO_TRANSFER_GAMMA10,
|
||||
SPA_VIDEO_TRANSFER_GAMMA18,
|
||||
SPA_VIDEO_TRANSFER_GAMMA20,
|
||||
SPA_VIDEO_TRANSFER_GAMMA22,
|
||||
SPA_VIDEO_TRANSFER_BT709,
|
||||
SPA_VIDEO_TRANSFER_SMPTE240M,
|
||||
SPA_VIDEO_TRANSFER_SRGB,
|
||||
SPA_VIDEO_TRANSFER_GAMMA28,
|
||||
SPA_VIDEO_TRANSFER_LOG100,
|
||||
SPA_VIDEO_TRANSFER_LOG316,
|
||||
SPA_VIDEO_TRANSFER_BT2020_12,
|
||||
SPA_VIDEO_TRANSFER_ADOBERGB
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo transfer_function_range[] = {
|
||||
{ "unknown", { sizeof (uint32_t), &transfer_functions[0] } },
|
||||
{ "gamma10", { sizeof (uint32_t), &transfer_functions[1] } },
|
||||
{ "gamma18", { sizeof (uint32_t), &transfer_functions[2] } },
|
||||
{ "gamma20", { sizeof (uint32_t), &transfer_functions[3] } },
|
||||
{ "gamma22", { sizeof (uint32_t), &transfer_functions[4] } },
|
||||
{ "bt709", { sizeof (uint32_t), &transfer_functions[5] } },
|
||||
{ "smpte240m", { sizeof (uint32_t), &transfer_functions[6] } },
|
||||
{ "srgb", { sizeof (uint32_t), &transfer_functions[7] } },
|
||||
{ "gamma28", { sizeof (uint32_t), &transfer_functions[8] } },
|
||||
{ "log100", { sizeof (uint32_t), &transfer_functions[9] } },
|
||||
{ "log316", { sizeof (uint32_t), &transfer_functions[10] } },
|
||||
{ "bt2020_12", { sizeof (uint32_t), &transfer_functions[11] } },
|
||||
{ "adobergb", { sizeof (uint32_t), &transfer_functions[12] } },
|
||||
};
|
||||
|
||||
static const uint32_t color_primaries[] = {
|
||||
SPA_VIDEO_COLOR_PRIMARIES_UNKNOWN,
|
||||
SPA_VIDEO_COLOR_PRIMARIES_BT709,
|
||||
SPA_VIDEO_COLOR_PRIMARIES_BT470M,
|
||||
SPA_VIDEO_COLOR_PRIMARIES_BT470BG,
|
||||
SPA_VIDEO_COLOR_PRIMARIES_SMPTE170M,
|
||||
SPA_VIDEO_COLOR_PRIMARIES_SMPTE240M,
|
||||
SPA_VIDEO_COLOR_PRIMARIES_FILM,
|
||||
SPA_VIDEO_COLOR_PRIMARIES_BT2020,
|
||||
SPA_VIDEO_COLOR_PRIMARIES_ADOBERGB
|
||||
};
|
||||
|
||||
static const SpaPropRangeInfo color_primaries_range[] = {
|
||||
{ "unknown", { sizeof (uint32_t), &color_primaries[0] } },
|
||||
{ "bt709", { sizeof (uint32_t), &color_primaries[1] } },
|
||||
{ "bt470M", { sizeof (uint32_t), &color_primaries[2] } },
|
||||
{ "bt470BG", { sizeof (uint32_t), &color_primaries[3] } },
|
||||
{ "smpte170m", { sizeof (uint32_t), &color_primaries[4] } },
|
||||
{ "smpte240m", { sizeof (uint32_t), &color_primaries[5] } },
|
||||
{ "film", { sizeof (uint32_t), &color_primaries[6] } },
|
||||
{ "bt2020", { sizeof (uint32_t), &color_primaries[7] } },
|
||||
{ "adobergb", { sizeof (uint32_t), &color_primaries[8] } },
|
||||
};
|
||||
|
||||
static const uint32_t min_uint32 = 1;
|
||||
static const uint32_t max_uint32 = UINT32_MAX;
|
||||
|
||||
static const SpaPropRangeInfo uint32_range[] = {
|
||||
{ "min", { sizeof (uint32_t), &min_uint32 } },
|
||||
{ "max", { sizeof (uint32_t), &max_uint32 } },
|
||||
};
|
||||
|
||||
static const SpaFraction min_framerate = { 0, 1 };
|
||||
static const SpaFraction max_framerate = { UINT32_MAX, 1 };
|
||||
|
||||
static const SpaPropRangeInfo framerate_range[] = {
|
||||
{ "min", { sizeof (SpaFraction), &min_framerate } },
|
||||
{ "max", { sizeof (SpaFraction), &max_framerate } },
|
||||
};
|
||||
|
||||
static const SpaPropInfo format_prop_info[] =
|
||||
static const ParseInfo *
|
||||
parse_info_find (const ParseInfo *info, uint32_t key, uint32_t type)
|
||||
{
|
||||
{ SPA_PROP_ID_VIDEO_INFO, 0,
|
||||
"info",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL | SPA_PROP_FLAG_INFO,
|
||||
SPA_PROP_TYPE_POINTER, sizeof (SpaVideoInfoRaw),
|
||||
SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_FORMAT, 0,
|
||||
"format",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (format_range), format_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_SIZE, 0,
|
||||
"size",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_RECTANGLE, sizeof (SpaRectangle),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, size_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_FRAMERATE, 0,
|
||||
"framerate",
|
||||
SPA_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, 0,
|
||||
"max-framerate",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_VIEWS, 0,
|
||||
"views",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, 0,
|
||||
"interlace-mode",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (interlace_mode_range), interlace_mode_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, 0,
|
||||
"pixel-aspect-ratio",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_FRACTION, sizeof (SpaFraction),
|
||||
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, framerate_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, 0,
|
||||
"multiview-mode",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (multiview_mode_range), multiview_mode_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, 0,
|
||||
"multiview-flags",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (multiview_flags_range), multiview_flags_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, 0,
|
||||
"chroma-site",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_FLAGS, SPA_N_ELEMENTS (chroma_site_range), chroma_site_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, 0,
|
||||
"color-range",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_range_range), color_range_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_MATRIX, 0,
|
||||
"color-matrix",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_matrix_range), color_matrix_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_TRANSFER_FUNCTION, 0,
|
||||
"transfer-function",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (transfer_function_range), transfer_function_range,
|
||||
NULL },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_PRIMARIES, 0,
|
||||
"color-primaries",
|
||||
SPA_PROP_FLAG_READWRITE | SPA_PROP_FLAG_OPTIONAL,
|
||||
SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
|
||||
SPA_PROP_RANGE_TYPE_ENUM, SPA_N_ELEMENTS (color_primaries_range), color_primaries_range,
|
||||
NULL },
|
||||
};
|
||||
|
||||
SpaResult
|
||||
spa_prop_info_fill_video (SpaPropInfo *info,
|
||||
SpaPropIdVideo id,
|
||||
size_t offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (info == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
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 - sizeof (SpaFormat) + sizeof (SpaProps);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
while (info->key) {
|
||||
if (info->key == key && info->type == type)
|
||||
return info;
|
||||
info++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_format_video_init (SpaMediaType type,
|
||||
SpaMediaSubType subtype,
|
||||
SpaFormatVideo *format)
|
||||
spa_format_video_parse (const SpaFormat *format,
|
||||
SpaVideoInfo *info)
|
||||
{
|
||||
SpaPropInfo *prop_info = NULL;
|
||||
unsigned int n_prop_info = 0;
|
||||
int i;
|
||||
SpaPODProp *prop;
|
||||
const ParseInfo *pinfo, *find;
|
||||
|
||||
if (type != SPA_MEDIA_TYPE_VIDEO)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
if (format->media_type != SPA_MEDIA_TYPE_VIDEO)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
switch (subtype) {
|
||||
switch (format->media_subtype) {
|
||||
case SPA_MEDIA_SUBTYPE_RAW:
|
||||
{
|
||||
static SpaPropInfo raw_prop_info[] = {
|
||||
{ SPA_PROP_ID_VIDEO_INFO, offsetof (SpaFormatVideo, info.raw) },
|
||||
{ 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) },
|
||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, offsetof (SpaFormatVideo, info.raw.max_framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_VIEWS, offsetof (SpaFormatVideo, info.raw.views) },
|
||||
{ SPA_PROP_ID_VIDEO_INTERLACE_MODE, offsetof (SpaFormatVideo, info.raw.interlace_mode) },
|
||||
{ SPA_PROP_ID_VIDEO_PIXEL_ASPECT_RATIO, offsetof (SpaFormatVideo, info.raw.pixel_aspect_ratio) },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_MODE, offsetof (SpaFormatVideo, info.raw.multiview_mode) },
|
||||
{ SPA_PROP_ID_VIDEO_MULTIVIEW_FLAGS, offsetof (SpaFormatVideo, info.raw.multiview_flags) },
|
||||
{ SPA_PROP_ID_VIDEO_CHROMA_SITE, offsetof (SpaFormatVideo, info.raw.chroma_site) },
|
||||
{ SPA_PROP_ID_VIDEO_COLOR_RANGE, offsetof (SpaFormatVideo, info.raw.color_range) },
|
||||
{ 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) },
|
||||
};
|
||||
static const SpaVideoInfoRaw default_raw_info = {
|
||||
SPA_VIDEO_FORMAT_UNKNOWN,
|
||||
{ 320, 240 },
|
||||
{ 25, 1 },
|
||||
{ 25, 1 },
|
||||
1,
|
||||
SPA_VIDEO_INTERLACE_MODE_PROGRESSIVE,
|
||||
{ 1, 1},
|
||||
SPA_VIDEO_MULTIVIEW_MODE_MONO,
|
||||
SPA_VIDEO_MULTIVIEW_FLAGS_NONE,
|
||||
SPA_VIDEO_CHROMA_SITE_UNKNOWN,
|
||||
SPA_VIDEO_COLOR_RANGE_UNKNOWN,
|
||||
SPA_VIDEO_COLOR_MATRIX_UNKNOWN,
|
||||
SPA_VIDEO_TRANSFER_UNKNOWN,
|
||||
SPA_VIDEO_COLOR_PRIMARIES_UNKNOWN
|
||||
};
|
||||
prop_info = raw_prop_info;
|
||||
n_prop_info = SPA_N_ELEMENTS (raw_prop_info);
|
||||
format->format.props.unset_mask = (1 << 15)-2;
|
||||
format->info.raw = default_raw_info;
|
||||
pinfo = raw_parse_info;
|
||||
break;
|
||||
}
|
||||
|
||||
case SPA_MEDIA_SUBTYPE_H264:
|
||||
{
|
||||
static SpaPropInfo h264_prop_info[] = {
|
||||
{ SPA_PROP_ID_VIDEO_INFO, offsetof (SpaFormatVideo, info.h264) },
|
||||
{ SPA_PROP_ID_VIDEO_SIZE, offsetof (SpaFormatVideo, info.h264.size) },
|
||||
{ SPA_PROP_ID_VIDEO_FRAMERATE, offsetof (SpaFormatVideo, info.h264.framerate) },
|
||||
{ SPA_PROP_ID_VIDEO_MAX_FRAMERATE, offsetof (SpaFormatVideo, info.h264.max_framerate) },
|
||||
};
|
||||
static const SpaVideoInfoH264 default_h264_info = {
|
||||
{ 320, 240 },
|
||||
{ 25, 1 },
|
||||
{ 25, 1 }
|
||||
};
|
||||
prop_info = h264_prop_info;
|
||||
n_prop_info = SPA_N_ELEMENTS (h264_prop_info);
|
||||
format->format.props.unset_mask = (1 << 4)-2;
|
||||
format->info.h264 = default_h264_info;
|
||||
pinfo = h264_parse_info;
|
||||
break;
|
||||
}
|
||||
|
||||
case SPA_MEDIA_SUBTYPE_MJPG:
|
||||
{
|
||||
static SpaPropInfo mjpg_prop_info[] = {
|
||||
{ SPA_PROP_ID_VIDEO_INFO, offsetof (SpaFormatVideo, info.mjpg) },
|
||||
{ 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) },
|
||||
};
|
||||
static const SpaVideoInfoMJPG default_mjpg_info = {
|
||||
{ 320, 240 },
|
||||
{ 25, 1 },
|
||||
{ 25, 1 }
|
||||
};
|
||||
prop_info = mjpg_prop_info;
|
||||
n_prop_info = SPA_N_ELEMENTS (mjpg_prop_info);
|
||||
format->format.props.unset_mask = (1 << 4)-2;
|
||||
format->info.mjpg = default_mjpg_info;
|
||||
pinfo = mjpg_parse_info;
|
||||
break;
|
||||
}
|
||||
|
||||
case SPA_MEDIA_SUBTYPE_DV:
|
||||
case SPA_MEDIA_SUBTYPE_MPEGTS:
|
||||
case SPA_MEDIA_SUBTYPE_H263:
|
||||
|
|
@ -587,76 +116,29 @@ spa_format_video_init (SpaMediaType type,
|
|||
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);
|
||||
info->media_type = format->media_type;
|
||||
info->media_subtype = format->media_subtype;
|
||||
|
||||
SPA_POD_OBJECT_BODY_FOREACH (&format->obj.body, format->obj.pod.size, prop) {
|
||||
if ((find = parse_info_find (pinfo, prop->body.key, prop->body.value.type))) {
|
||||
memcpy (SPA_MEMBER (info, find->offset, void),
|
||||
SPA_POD_BODY (&prop->body.value),
|
||||
SPA_POD_BODY_SIZE (&prop->body.value));
|
||||
}
|
||||
|
||||
format->format.media_type = type;
|
||||
format->format.media_subtype = subtype;
|
||||
format->format.props.n_prop_info = n_prop_info;
|
||||
format->format.props.prop_info = prop_info;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_format_video_parse (const SpaFormat *format,
|
||||
SpaFormatVideo *vformat)
|
||||
{
|
||||
SpaPropValue value;
|
||||
const SpaProps *props;
|
||||
SpaResult res;
|
||||
unsigned int idx;
|
||||
|
||||
if ((void *)format == (void *)vformat)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
if (format->media_type != SPA_MEDIA_TYPE_VIDEO)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
if ((res = spa_format_video_init (format->media_type,
|
||||
format->media_subtype,
|
||||
vformat)) < 0)
|
||||
return res;
|
||||
|
||||
props = &format->props;
|
||||
idx = spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_INFO);
|
||||
if ((res = spa_props_get_value (props, idx, &value)) < 0)
|
||||
goto fallback;
|
||||
|
||||
if (props->prop_info[idx].type != SPA_PROP_TYPE_POINTER)
|
||||
goto fallback;
|
||||
|
||||
memcpy (&vformat->info, value.value, SPA_MIN (value.size, sizeof (vformat->info)));
|
||||
vformat->format.props.unset_mask = props->unset_mask;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
fallback:
|
||||
res = spa_props_copy_values (props, &vformat->format.props);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
prop_finish (SpaPropBuilder *b)
|
||||
{
|
||||
b->dest = malloc (b->size);
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_format_filter (const SpaFormat *format,
|
||||
const SpaFormat *filter,
|
||||
SpaFormat **result)
|
||||
SpaPODBuilder *result)
|
||||
{
|
||||
SpaPropBuilder b;
|
||||
SpaResult res;
|
||||
if (format == NULL || result == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
if (filter == NULL) {
|
||||
*result = (SpaFormat *) format;
|
||||
spa_pod_builder_raw (result, format, SPA_FORMAT_SIZE (format), true);
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -664,36 +146,7 @@ spa_format_filter (const SpaFormat *format,
|
|||
filter->media_subtype != format->media_subtype)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
spa_prop_builder_init (&b, sizeof (SpaFormatVideo), offsetof(SpaFormatVideo, format.props));
|
||||
b.finish = prop_finish;
|
||||
if ((res = spa_props_filter (&b, &format->props, &filter->props)) != SPA_RESULT_OK)
|
||||
return res;
|
||||
spa_pod_builder_raw (result, format, SPA_FORMAT_SIZE (format), true);
|
||||
|
||||
*result = b.dest;
|
||||
(*result)->media_type = format->media_type;
|
||||
(*result)->media_subtype = format->media_subtype;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
SpaResult
|
||||
spa_format_video_builder_add (SpaPropBuilder *b,
|
||||
SpaPropBuilderInfo *info,
|
||||
SpaPropIdVideo id,
|
||||
size_t offset)
|
||||
{
|
||||
spa_prop_info_fill_video (&info->info, id, offset);
|
||||
spa_prop_builder_add_info (b, info);
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
SpaResult
|
||||
spa_format_video_builder_add_range (SpaPropBuilder *b,
|
||||
SpaPropBuilderRange *range,
|
||||
int index)
|
||||
{
|
||||
range->info = b->info->info.range_values[index];
|
||||
spa_prop_builder_add_range (b, range);
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
/* Simple Plugin API
|
||||
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SPA_LIBVIDEO_RAW_H__
|
||||
#define __SPA_LIBVIDEO_RAW_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <lib/prop-builder.h>
|
||||
|
||||
SpaResult spa_format_video_builder_add (SpaPropBuilder *b,
|
||||
SpaPropBuilderInfo *info,
|
||||
SpaPropIdVideo id,
|
||||
size_t offset);
|
||||
|
||||
SpaResult spa_format_video_builder_add_range (SpaPropBuilder *b,
|
||||
SpaPropBuilderRange *range,
|
||||
int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __SPA_LIBVIDEO_RAW_H__ */
|
||||
|
|
@ -330,6 +330,10 @@ spa_alsa_sink_node_port_enum_formats (SpaNode *node,
|
|||
unsigned int index)
|
||||
{
|
||||
SpaALSASink *this;
|
||||
SpaResult res;
|
||||
SpaFormat *fmt;
|
||||
uint8_t buffer[1024];
|
||||
SpaPODBuilder b = { buffer, sizeof (buffer), };
|
||||
|
||||
if (node == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -341,19 +345,43 @@ spa_alsa_sink_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&this->query_format);
|
||||
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
|
||||
SPA_AUDIO_FORMAT_S16,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_ENUM, 2,
|
||||
SPA_AUDIO_FORMAT_S16,
|
||||
SPA_AUDIO_FORMAT_S32,
|
||||
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
|
||||
44100,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, INT32_MAX,
|
||||
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
|
||||
2,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, INT32_MAX,
|
||||
0), SpaFormat);
|
||||
break;
|
||||
case 1:
|
||||
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
|
||||
SPA_MEDIA_SUBTYPE_AAC,
|
||||
&this->query_format);
|
||||
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_AAC,
|
||||
0), SpaFormat);
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = &this->query_format.format;
|
||||
|
||||
b.data = this->format_buffer;
|
||||
b.size = sizeof (this->format_buffer);
|
||||
b.offset = 0;
|
||||
|
||||
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
|
||||
return res;
|
||||
|
||||
*format = SPA_MEMBER (b.data, 0, SpaFormat);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -456,7 +484,7 @@ spa_alsa_sink_node_port_get_format (SpaNode *node,
|
|||
if (!this->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = &this->current_format.format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -367,6 +367,9 @@ spa_alsa_source_node_port_enum_formats (SpaNode *node,
|
|||
{
|
||||
SpaALSASource *this;
|
||||
SpaResult res;
|
||||
SpaFormat *fmt;
|
||||
uint8_t buffer[256];
|
||||
SpaPODBuilder b = { buffer, sizeof (buffer), };
|
||||
|
||||
if (node == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -378,23 +381,42 @@ spa_alsa_source_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&this->query_format);
|
||||
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
|
||||
SPA_AUDIO_FORMAT_S16,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_ENUM, 2,
|
||||
SPA_AUDIO_FORMAT_S16,
|
||||
SPA_AUDIO_FORMAT_S32,
|
||||
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
|
||||
44100,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, INT32_MAX,
|
||||
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
|
||||
2,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, INT32_MAX,
|
||||
0), SpaFormat);
|
||||
break;
|
||||
case 1:
|
||||
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
|
||||
SPA_MEDIA_SUBTYPE_AAC,
|
||||
&this->query_format);
|
||||
break;
|
||||
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_AAC,
|
||||
0), SpaFormat);
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
|
||||
if ((res = spa_format_audio_filter (&this->query_format, filter)) != SPA_RESULT_OK)
|
||||
b.data = this->format_buffer;
|
||||
b.size = sizeof (this->format_buffer);
|
||||
b.offset = 0;
|
||||
|
||||
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
|
||||
return res;
|
||||
|
||||
*format = &this->query_format.format;
|
||||
*format = SPA_MEMBER (this->format_buffer, 0, SpaFormat);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -502,7 +524,7 @@ spa_alsa_source_node_port_get_format (SpaNode *node,
|
|||
if (!this->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = &this->current_format.format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ spa_alsa_format_to_alsa (SpaAudioFormat format)
|
|||
}
|
||||
|
||||
int
|
||||
spa_alsa_set_format (SpaALSAState *state, SpaFormatAudio *fmt, SpaPortFormatFlags flags)
|
||||
spa_alsa_set_format (SpaALSAState *state, SpaAudioInfo *fmt, SpaPortFormatFlags flags)
|
||||
{
|
||||
unsigned int rrate, rchannels;
|
||||
snd_pcm_uframes_t period_size;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ extern "C" {
|
|||
#include <spa/loop.h>
|
||||
#include <spa/ringbuffer.h>
|
||||
#include <spa/audio/format.h>
|
||||
#include <spa/format-builder.h>
|
||||
|
||||
typedef struct _SpaALSAState SpaALSAState;
|
||||
typedef struct _SpaALSABuffer SpaALSABuffer;
|
||||
|
|
@ -89,8 +90,9 @@ struct _SpaALSAState {
|
|||
snd_pcm_t *hndl;
|
||||
|
||||
bool have_format;
|
||||
SpaFormatAudio query_format;
|
||||
SpaFormatAudio current_format;
|
||||
SpaAudioInfo current_format;
|
||||
uint8_t format_buffer[1024];
|
||||
|
||||
snd_pcm_sframes_t buffer_frames;
|
||||
snd_pcm_sframes_t period_frames;
|
||||
snd_pcm_format_t format;
|
||||
|
|
@ -125,7 +127,7 @@ struct _SpaALSAState {
|
|||
};
|
||||
|
||||
int spa_alsa_set_format (SpaALSAState *state,
|
||||
SpaFormatAudio *fmt,
|
||||
SpaAudioInfo *info,
|
||||
SpaPortFormatFlags flags);
|
||||
|
||||
SpaResult spa_alsa_start (SpaALSAState *state, bool xrun_recover);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ struct _MixerBuffer {
|
|||
typedef struct {
|
||||
bool valid;
|
||||
bool have_format;
|
||||
SpaFormatAudio format[2];
|
||||
SpaAudioInfo format;
|
||||
SpaAudioMixerPortProps props[2];
|
||||
SpaPortInfo info;
|
||||
size_t buffer_index;
|
||||
|
|
@ -328,14 +328,11 @@ spa_audiomixer_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&port->format[0]);
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = &port->format[0].format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -366,7 +363,7 @@ spa_audiomixer_node_port_set_format (SpaNode *node,
|
|||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
if ((res = spa_format_audio_parse (format, &port->format[1])) < 0)
|
||||
if ((res = spa_format_audio_parse (format, &port->format)) < 0)
|
||||
return res;
|
||||
|
||||
port->have_format = true;
|
||||
|
|
@ -396,7 +393,7 @@ spa_audiomixer_node_port_get_format (SpaNode *node,
|
|||
if (!port->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = &port->format[1].format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <spa/node.h>
|
||||
#include <spa/list.h>
|
||||
#include <spa/audio/format.h>
|
||||
#include <spa/format-builder.h>
|
||||
#include <lib/props.h>
|
||||
|
||||
#define SAMPLES_TO_TIME(this,s) ((s) * SPA_NSEC_PER_SEC / (this)->current_format.info.raw.rate)
|
||||
|
|
@ -88,8 +89,8 @@ struct _SpaAudioTestSrc {
|
|||
SpaPortOutput *output;
|
||||
|
||||
bool have_format;
|
||||
SpaFormatAudio query_format;
|
||||
SpaFormatAudio current_format;
|
||||
SpaAudioInfo current_format;
|
||||
uint8_t format_buffer[1024];
|
||||
size_t bpf;
|
||||
|
||||
ATSBuffer buffers[MAX_BUFFERS];
|
||||
|
|
@ -469,6 +470,9 @@ spa_audiotestsrc_node_port_enum_formats (SpaNode *node,
|
|||
{
|
||||
SpaAudioTestSrc *this;
|
||||
SpaResult res;
|
||||
SpaFormat *fmt;
|
||||
uint8_t buffer[256];
|
||||
SpaPODBuilder b = { buffer, sizeof (buffer), };
|
||||
|
||||
if (node == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -480,17 +484,40 @@ spa_audiotestsrc_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&this->query_format);
|
||||
{
|
||||
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
|
||||
SPA_AUDIO_FORMAT_S16,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_ENUM, 2,
|
||||
SPA_AUDIO_FORMAT_S16,
|
||||
SPA_AUDIO_FORMAT_S32,
|
||||
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
|
||||
44100,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, INT32_MAX,
|
||||
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
|
||||
2,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, INT32_MAX,
|
||||
0), SpaFormat);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
if ((res = spa_format_audio_filter (&this->query_format, filter)) != SPA_RESULT_OK)
|
||||
|
||||
b.data = this->format_buffer;
|
||||
b.size = sizeof (this->format_buffer);
|
||||
b.offset = 0;
|
||||
|
||||
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
|
||||
return res;
|
||||
|
||||
*format = &this->query_format.format;
|
||||
*format = SPA_MEMBER (this->format_buffer, 0, SpaFormat);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -569,6 +596,7 @@ spa_audiotestsrc_node_port_get_format (SpaNode *node,
|
|||
const SpaFormat **format)
|
||||
{
|
||||
SpaAudioTestSrc *this;
|
||||
SpaPODBuilder b = { NULL, };
|
||||
|
||||
if (node == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -581,7 +609,21 @@ spa_audiotestsrc_node_port_get_format (SpaNode *node,
|
|||
if (!this->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = &this->current_format.format;
|
||||
b.data = this->format_buffer;
|
||||
b.size = sizeof (this->format_buffer);
|
||||
|
||||
*format = SPA_MEMBER (b.data, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
|
||||
this->current_format.info.raw.format,
|
||||
SPA_POD_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
|
||||
this->current_format.info.raw.rate,
|
||||
SPA_POD_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
|
||||
this->current_format.info.raw.channels,
|
||||
SPA_POD_PROP_FLAG_READWRITE,
|
||||
0), SpaFormat);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,8 +51,9 @@ struct _FFMpegBuffer {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
SpaFormatVideo format[2];
|
||||
SpaFormat *current_format;
|
||||
bool have_format;
|
||||
SpaVideoInfo query_format;
|
||||
SpaVideoInfo current_format;
|
||||
bool have_buffers;
|
||||
FFMpegBuffer buffers[MAX_BUFFERS];
|
||||
SpaPortInfo info;
|
||||
|
|
@ -268,14 +269,11 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&port->format[0]);
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = &port->format[0].format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -302,16 +300,16 @@ spa_ffmpeg_dec_node_port_set_format (SpaNode *node,
|
|||
port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
|
||||
|
||||
if (format == NULL) {
|
||||
port->current_format = NULL;
|
||||
port->have_format = false;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
if ((res = spa_format_video_parse (format, &port->format[0]) < 0))
|
||||
if ((res = spa_format_video_parse (format, &port->query_format) < 0))
|
||||
return res;
|
||||
|
||||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||
memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo));
|
||||
port->current_format = &port->format[1].format;
|
||||
memcpy (&port->current_format, &port->query_format, sizeof (SpaVideoInfo));
|
||||
port->have_format = true;
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
@ -336,10 +334,10 @@ spa_ffmpeg_dec_node_port_get_format (SpaNode *node,
|
|||
|
||||
port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
|
||||
|
||||
if (port->current_format == NULL)
|
||||
if (!port->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = port->current_format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -476,7 +474,7 @@ spa_ffmpeg_dec_node_process_output (SpaNode *node)
|
|||
if ((output = port->io) == NULL)
|
||||
return SPA_RESULT_ERROR;
|
||||
|
||||
if (port->current_format == NULL) {
|
||||
if (!port->have_format) {
|
||||
output->status = SPA_RESULT_NO_FORMAT;
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ struct _FFMpegBuffer {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
SpaFormatVideo format[2];
|
||||
SpaVideoInfo format[2];
|
||||
SpaFormat *current_format;
|
||||
bool have_buffers;
|
||||
FFMpegBuffer buffers[MAX_BUFFERS];
|
||||
|
|
@ -273,14 +273,11 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&port->format[0]);
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = &port->format[0].format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -310,16 +307,17 @@ spa_ffmpeg_enc_node_port_set_format (SpaNode *node,
|
|||
port->current_format = NULL;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
if ((res = spa_format_video_parse (format, &port->format[0]) < 0))
|
||||
return res;
|
||||
|
||||
if (format->media_type != SPA_MEDIA_TYPE_VIDEO ||
|
||||
format->media_subtype != SPA_MEDIA_SUBTYPE_RAW)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
if ((res = spa_format_video_parse (format, &port->format[0]) < 0))
|
||||
return res;
|
||||
|
||||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||
memcpy (&port->format[1], &port->format[0], sizeof (SpaFormatVideo));
|
||||
port->current_format = &port->format[1].format;
|
||||
memcpy (&port->format[1], &port->format[0], sizeof (SpaVideoInfo));
|
||||
port->current_format = NULL;
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <spa/log.h>
|
||||
#include <spa/loop.h>
|
||||
#include <spa/id-map.h>
|
||||
#include <spa/format-builder.h>
|
||||
#include <lib/debug.h>
|
||||
#include <lib/props.h>
|
||||
|
||||
|
|
@ -63,23 +64,6 @@ struct _V4l2Buffer {
|
|||
struct v4l2_buffer v4l2_buffer;
|
||||
};
|
||||
|
||||
typedef struct _V4l2Format V4l2Format;
|
||||
|
||||
struct _V4l2Format {
|
||||
SpaFormat fmt;
|
||||
SpaVideoFormat format;
|
||||
SpaRectangle size;
|
||||
SpaFraction framerate;
|
||||
SpaVideoInterlaceMode interlace_mode;
|
||||
SpaVideoColorRange color_range;
|
||||
SpaVideoColorMatrix color_matrix;
|
||||
SpaVideoTransferFunction transfer_function;
|
||||
SpaVideoColorPrimaries color_primaries;
|
||||
SpaPropInfo infos[16];
|
||||
SpaPropRangeInfo ranges[16];
|
||||
SpaFraction framerates[16];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t node;
|
||||
uint32_t clock;
|
||||
|
|
@ -99,8 +83,9 @@ typedef struct {
|
|||
struct v4l2_frmsizeenum frmsize;
|
||||
struct v4l2_frmivalenum frmival;
|
||||
|
||||
V4l2Format format[2];
|
||||
V4l2Format *current_format;
|
||||
bool have_format;
|
||||
SpaVideoInfo current_format;
|
||||
uint8_t format_buffer[1024];
|
||||
|
||||
int fd;
|
||||
bool opened;
|
||||
|
|
@ -357,7 +342,7 @@ spa_v4l2_source_node_send_command (SpaNode *node,
|
|||
SpaV4l2State *state = &this->state[0];
|
||||
SpaResult res;
|
||||
|
||||
if (state->current_format == NULL)
|
||||
if (!state->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
if (state->n_buffers == 0)
|
||||
|
|
@ -380,7 +365,7 @@ spa_v4l2_source_node_send_command (SpaNode *node,
|
|||
{
|
||||
SpaV4l2State *state = &this->state[0];
|
||||
|
||||
if (state->current_format == NULL)
|
||||
if (!state->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
if (state->n_buffers == 0)
|
||||
|
|
@ -483,28 +468,6 @@ spa_v4l2_source_node_remove_port (SpaNode *node,
|
|||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
spa_v4l2_format_init (V4l2Format *f, const SpaFormat *sf)
|
||||
{
|
||||
f->fmt.props.n_prop_info = 3;
|
||||
f->fmt.props.prop_info = f->infos;
|
||||
|
||||
spa_prop_info_fill_video (&f->infos[0],
|
||||
SPA_PROP_ID_VIDEO_FORMAT,
|
||||
offsetof (V4l2Format, format));
|
||||
spa_prop_info_fill_video (&f->infos[1],
|
||||
SPA_PROP_ID_VIDEO_SIZE,
|
||||
offsetof (V4l2Format, size));
|
||||
spa_prop_info_fill_video (&f->infos[2],
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||
offsetof (V4l2Format, framerate));
|
||||
|
||||
f->fmt.media_type = sf->media_type;
|
||||
f->fmt.media_subtype = sf->media_subtype;
|
||||
|
||||
return spa_props_copy_values (&sf->props, &f->fmt.props);
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
spa_v4l2_source_node_port_enum_formats (SpaNode *node,
|
||||
SpaDirection direction,
|
||||
|
|
@ -539,7 +502,7 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
|
|||
SpaV4l2Source *this;
|
||||
SpaV4l2State *state;
|
||||
SpaResult res;
|
||||
V4l2Format *f, *tf;
|
||||
SpaVideoInfo info;
|
||||
|
||||
if (node == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -555,43 +518,34 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
|
|||
spa_v4l2_stream_off (this);
|
||||
spa_v4l2_clear_buffers (this);
|
||||
spa_v4l2_close (this);
|
||||
state->current_format = NULL;
|
||||
state->have_format = false;
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
f = &state->format[0];
|
||||
tf = &state->format[1];
|
||||
|
||||
if ((SpaFormat*)f != format) {
|
||||
if ((res = spa_v4l2_format_init (f, format)) < 0)
|
||||
if ((res = spa_format_video_parse (format, &info)) < 0)
|
||||
return res;
|
||||
} else {
|
||||
f = (V4l2Format*)format;
|
||||
}
|
||||
|
||||
if (state->current_format) {
|
||||
if (f->fmt.media_type == state->current_format->fmt.media_type &&
|
||||
f->fmt.media_subtype == state->current_format->fmt.media_subtype &&
|
||||
f->format == state->current_format->format &&
|
||||
f->size.width == state->current_format->size.width &&
|
||||
f->size.height == state->current_format->size.height)
|
||||
if (state->have_format) {
|
||||
if (info.media_type == state->current_format.media_type &&
|
||||
info.media_subtype == state->current_format.media_subtype &&
|
||||
info.info.raw.format == state->current_format.info.raw.format &&
|
||||
info.info.raw.size.width == state->current_format.info.raw.size.width &&
|
||||
info.info.raw.size.height == state->current_format.info.raw.size.height)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||
spa_v4l2_use_buffers (this, NULL, 0);
|
||||
state->current_format = NULL;
|
||||
state->have_format = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (spa_v4l2_set_format (this, f, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0)
|
||||
if (spa_v4l2_set_format (this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||
if ((res = spa_v4l2_format_init (tf, &f->fmt)) < 0)
|
||||
return res;
|
||||
state->current_format = tf;
|
||||
|
||||
state->current_format = info;
|
||||
state->have_format = true;
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
|
||||
|
|
@ -606,6 +560,7 @@ spa_v4l2_source_node_port_get_format (SpaNode *node,
|
|||
{
|
||||
SpaV4l2Source *this;
|
||||
SpaV4l2State *state;
|
||||
SpaPODBuilder b = { NULL, };
|
||||
|
||||
if (node == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -617,10 +572,26 @@ spa_v4l2_source_node_port_get_format (SpaNode *node,
|
|||
|
||||
state = &this->state[port_id];
|
||||
|
||||
if (state->current_format == NULL)
|
||||
if (!state->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = &state->current_format->fmt;
|
||||
b.data = state->format_buffer;
|
||||
b.size = sizeof (state->format_buffer);
|
||||
|
||||
*format = SPA_MEMBER (b.data, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
|
||||
state->current_format.info.raw.format,
|
||||
SPA_POD_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE,
|
||||
state->current_format.info.raw.size.width,
|
||||
state->current_format.info.raw.size.height,
|
||||
SPA_POD_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION,
|
||||
state->current_format.info.raw.framerate.num,
|
||||
state->current_format.info.raw.framerate.denom,
|
||||
SPA_POD_PROP_FLAG_READWRITE,
|
||||
0), SpaFormat);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -685,7 +656,7 @@ spa_v4l2_source_node_port_use_buffers (SpaNode *node,
|
|||
|
||||
state = &this->state[port_id];
|
||||
|
||||
if (state->current_format == NULL)
|
||||
if (!state->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
if (state->n_buffers) {
|
||||
|
|
@ -728,7 +699,7 @@ spa_v4l2_source_node_port_alloc_buffers (SpaNode *node,
|
|||
|
||||
state = &this->state[port_id];
|
||||
|
||||
if (state->current_format == NULL)
|
||||
if (!state->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
res = spa_v4l2_alloc_buffers (this, params, n_params, buffers, n_buffers);
|
||||
|
|
@ -1003,6 +974,7 @@ v4l2_source_init (const SpaHandleFactory *factory,
|
|||
strncpy (this->props[1].device, str, 63);
|
||||
this->props[1].props.unset_mask &= ~1;
|
||||
}
|
||||
this->props[1].props.unset_mask &= ~1;
|
||||
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
|
||||
|
|
|
|||
|
|
@ -328,27 +328,25 @@ enum_filter_format (const SpaFormat *filter, unsigned int index)
|
|||
|
||||
if ((filter->media_type == SPA_MEDIA_TYPE_VIDEO || filter->media_type == SPA_MEDIA_TYPE_IMAGE)) {
|
||||
if (filter->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
||||
SpaPropValue val;
|
||||
SpaResult res;
|
||||
unsigned int idx;
|
||||
const SpaPropInfo *pi;
|
||||
SpaPODProp *p;
|
||||
unsigned int n_values;
|
||||
const uint32_t *values;
|
||||
|
||||
idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FORMAT);
|
||||
if (idx == SPA_IDX_INVALID)
|
||||
if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_FORMAT)))
|
||||
return SPA_VIDEO_FORMAT_UNKNOWN;
|
||||
|
||||
pi = &filter->props.prop_info[idx];
|
||||
if (pi->type != SPA_PROP_TYPE_UINT32)
|
||||
if (p->body.value.type != SPA_PROP_TYPE_INT)
|
||||
return SPA_VIDEO_FORMAT_UNKNOWN;
|
||||
|
||||
res = spa_props_get_value (&filter->props, idx, &val);
|
||||
if (res >= 0) {
|
||||
values = SPA_POD_BODY_CONST (&p->body.value);
|
||||
n_values = SPA_POD_PROP_N_VALUES (p);
|
||||
|
||||
if (p->body.flags & SPA_POD_PROP_FLAG_UNSET) {
|
||||
if (index + 1 < n_values)
|
||||
video_format = values[index + 1];
|
||||
} else {
|
||||
if (index == 0)
|
||||
video_format = *((SpaVideoFormat *)val.value);
|
||||
} else if (res == SPA_RESULT_PROPERTY_UNSET) {
|
||||
|
||||
if (index < pi->n_range_values)
|
||||
video_format = *((SpaVideoFormat *)pi->range_values[index].val.value);
|
||||
video_format = values[0];
|
||||
}
|
||||
} else {
|
||||
if (index == 0)
|
||||
|
|
@ -453,9 +451,12 @@ spa_v4l2_enum_format (SpaV4l2Source *this,
|
|||
unsigned int index)
|
||||
{
|
||||
SpaV4l2State *state = &this->state[0];
|
||||
int res, i, pi;
|
||||
V4l2Format *fmt;
|
||||
int res;
|
||||
const FormatInfo *info;
|
||||
SpaPODFrame f[2];
|
||||
SpaPODProp *prop;
|
||||
SpaFormat *fmt;
|
||||
SpaPODBuilder b = { state->format_buffer, sizeof (state->format_buffer), };
|
||||
|
||||
if (spa_v4l2_open (this) < 0)
|
||||
return SPA_RESULT_ERROR;
|
||||
|
|
@ -506,37 +507,30 @@ next_fmtdesc:
|
|||
state->frmsize.pixel_format = state->fmtdesc.pixelformat;
|
||||
state->next_frmsize = true;
|
||||
}
|
||||
|
||||
if (!(info = fourcc_to_format_info (state->fmtdesc.pixelformat)))
|
||||
goto next_fmtdesc;
|
||||
|
||||
next_frmsize:
|
||||
while (state->next_frmsize) {
|
||||
if (filter) {
|
||||
const SpaPropInfo *pi;
|
||||
unsigned int idx;
|
||||
SpaPropValue val;
|
||||
SpaResult res;
|
||||
SpaPODProp *p;
|
||||
|
||||
/* check if we have a fixed frame size */
|
||||
idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_SIZE);
|
||||
if (idx == SPA_IDX_INVALID)
|
||||
if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_SIZE)))
|
||||
goto do_frmsize;
|
||||
|
||||
pi = &filter->props.prop_info[idx];
|
||||
if (pi->type != SPA_PROP_TYPE_RECTANGLE)
|
||||
if (p->body.value.type != SPA_PROP_TYPE_RECTANGLE)
|
||||
return SPA_RESULT_ENUM_END;
|
||||
|
||||
res = spa_props_get_value (&filter->props, idx, &val);
|
||||
if (res >= 0) {
|
||||
const SpaRectangle *size = val.value;
|
||||
if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) {
|
||||
const SpaRectangle *values = SPA_POD_BODY_CONST (&p->body.value);
|
||||
|
||||
if (state->frmsize.index > 0)
|
||||
goto next_fmtdesc;
|
||||
|
||||
state->frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
||||
state->frmsize.discrete.width = size->width;
|
||||
state->frmsize.discrete.height = size->height;
|
||||
state->frmsize.discrete.width = values[0].width;
|
||||
state->frmsize.discrete.height = values[0].height;
|
||||
goto have_size;
|
||||
}
|
||||
}
|
||||
|
|
@ -549,33 +543,33 @@ do_frmsize:
|
|||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
if (filter) {
|
||||
const SpaPropInfo *pi;
|
||||
unsigned int idx;
|
||||
const SpaRectangle step = { 1, 1 };
|
||||
SpaPODProp *p;
|
||||
const SpaRectangle step = { 1, 1 }, *values;
|
||||
uint32_t range;
|
||||
unsigned int i, n_values;
|
||||
|
||||
/* check if we have a fixed frame size */
|
||||
idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_SIZE);
|
||||
if (idx == SPA_IDX_INVALID)
|
||||
if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_SIZE)))
|
||||
goto have_size;
|
||||
|
||||
/* checked above */
|
||||
pi = &filter->props.prop_info[idx];
|
||||
range = p->body.flags & SPA_POD_PROP_RANGE_MASK;
|
||||
values = SPA_POD_BODY_CONST (&p->body.value);
|
||||
n_values = SPA_POD_PROP_N_VALUES (p);
|
||||
|
||||
if (pi->range_type == SPA_PROP_RANGE_TYPE_MIN_MAX) {
|
||||
if (filter_framesize (&state->frmsize, pi->range_values[0].val.value,
|
||||
pi->range_values[1].val.value,
|
||||
if (range == SPA_POD_PROP_RANGE_MIN_MAX && n_values > 2) {
|
||||
if (filter_framesize (&state->frmsize, &values[1],
|
||||
&values[2],
|
||||
&step))
|
||||
goto have_size;
|
||||
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_STEP) {
|
||||
if (filter_framesize (&state->frmsize, pi->range_values[0].val.value,
|
||||
pi->range_values[1].val.value,
|
||||
pi->range_values[2].val.value))
|
||||
} else if (range == SPA_PROP_RANGE_TYPE_STEP && n_values > 3) {
|
||||
if (filter_framesize (&state->frmsize, &values[1],
|
||||
&values[2],
|
||||
&values[3]))
|
||||
goto have_size;
|
||||
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_ENUM) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < pi->n_range_values; i++) {
|
||||
if (filter_framesize (&state->frmsize, pi->range_values[i].val.value,
|
||||
pi->range_values[i].val.value,
|
||||
} else if (range == SPA_PROP_RANGE_TYPE_ENUM) {
|
||||
for (i = 1; i < n_values; i++) {
|
||||
if (filter_framesize (&state->frmsize, &values[i],
|
||||
&values[i],
|
||||
&step))
|
||||
goto have_size;
|
||||
}
|
||||
|
|
@ -608,43 +602,44 @@ have_size:
|
|||
}
|
||||
}
|
||||
|
||||
fmt = &state->format[0];
|
||||
fmt->fmt.media_type = info->media_type;
|
||||
fmt->fmt.media_subtype = info->media_subtype;
|
||||
fmt->fmt.props.prop_info = fmt->infos;
|
||||
fmt->fmt.props.n_prop_info = pi = 0;
|
||||
fmt->fmt.props.unset_mask = 0;
|
||||
fmt = SPA_MEMBER (b.data,
|
||||
spa_pod_builder_push_format (&b, &f[0],
|
||||
info->media_type,
|
||||
info->media_subtype),
|
||||
SpaFormat);
|
||||
|
||||
if (info->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
||||
spa_prop_info_fill_video (&fmt->infos[pi],
|
||||
SPA_PROP_ID_VIDEO_FORMAT,
|
||||
offsetof (V4l2Format, format));
|
||||
fmt->format = info->format;
|
||||
pi = ++fmt->fmt.props.n_prop_info;
|
||||
} else {
|
||||
fmt->format = info->format;
|
||||
spa_pod_builder_format_prop (&b,
|
||||
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
|
||||
info->format,
|
||||
SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READWRITE,
|
||||
0);
|
||||
}
|
||||
|
||||
spa_prop_info_fill_video (&fmt->infos[pi],
|
||||
SPA_PROP_ID_VIDEO_SIZE,
|
||||
offsetof (V4l2Format, size));
|
||||
fmt->size.width = state->frmsize.discrete.width;
|
||||
fmt->size.height = state->frmsize.discrete.height;
|
||||
pi = ++fmt->fmt.props.n_prop_info;
|
||||
spa_pod_builder_format_prop (&b,
|
||||
SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE,
|
||||
state->frmsize.discrete.width,
|
||||
state->frmsize.discrete.height,
|
||||
SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READWRITE,
|
||||
0);
|
||||
|
||||
spa_prop_info_fill_video (&fmt->infos[pi],
|
||||
prop = SPA_MEMBER (b.data,
|
||||
spa_pod_builder_push_prop (&b, &f[1],
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||
offsetof (V4l2Format, framerate));
|
||||
fmt->infos[pi].range_values = fmt->ranges;
|
||||
fmt->infos[pi].n_range_values = 0;
|
||||
i = state->frmival.index = 0;
|
||||
SPA_POD_PROP_RANGE_NONE |
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_FLAG_READWRITE),
|
||||
SpaPODProp);
|
||||
spa_pod_builder_fraction (&b, 25, 1);
|
||||
|
||||
state->frmival.index = 0;
|
||||
|
||||
while (true) {
|
||||
if ((res = xioctl (state->fd, VIDIOC_ENUM_FRAMEINTERVALS, &state->frmival)) < 0) {
|
||||
if (errno == EINVAL) {
|
||||
state->frmsize.index++;
|
||||
state->next_frmsize = true;
|
||||
if (i == 0)
|
||||
if (state->frmival.index == 0)
|
||||
goto next_frmsize;
|
||||
break;
|
||||
}
|
||||
|
|
@ -652,42 +647,40 @@ have_size:
|
|||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
if (filter) {
|
||||
SpaPropValue val;
|
||||
const SpaPropInfo *pi;
|
||||
unsigned int idx;
|
||||
SpaResult res;
|
||||
const SpaFraction step = { 1, 1 };
|
||||
SpaPODProp *p;
|
||||
uint32_t range;
|
||||
unsigned int i, n_values;
|
||||
const SpaFraction step = { 1, 1 }, *values;
|
||||
|
||||
/* check against filter */
|
||||
idx = spa_props_index_for_id (&filter->props, SPA_PROP_ID_VIDEO_FRAMERATE);
|
||||
if (idx == SPA_IDX_INVALID)
|
||||
if (!(p = spa_pod_object_body_find_prop (&filter->obj.body, filter->obj.pod.size, SPA_PROP_ID_VIDEO_FRAMERATE)))
|
||||
goto have_framerate;
|
||||
|
||||
pi = &filter->props.prop_info[idx];
|
||||
if (pi->type != SPA_PROP_TYPE_FRACTION)
|
||||
if (p->body.value.type != SPA_PROP_TYPE_FRACTION)
|
||||
return SPA_RESULT_ENUM_END;
|
||||
|
||||
res = spa_props_get_value (&filter->props, idx, &val);
|
||||
if (res == 0) {
|
||||
if (filter_framerate (&state->frmival, val.value,
|
||||
val.value,
|
||||
range = p->body.flags & SPA_POD_PROP_RANGE_MASK;
|
||||
values = SPA_POD_BODY_CONST (&p->body.value);
|
||||
n_values = SPA_POD_PROP_N_VALUES (p);
|
||||
|
||||
if (!(p->body.flags & SPA_POD_PROP_FLAG_UNSET)) {
|
||||
if (filter_framerate (&state->frmival, &values[0],
|
||||
&values[0],
|
||||
&step))
|
||||
goto have_framerate;
|
||||
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_MIN_MAX) {
|
||||
if (filter_framerate (&state->frmival, pi->range_values[0].val.value,
|
||||
pi->range_values[1].val.value,
|
||||
} else if (range == SPA_PROP_RANGE_TYPE_MIN_MAX && n_values > 2) {
|
||||
if (filter_framerate (&state->frmival, &values[1],
|
||||
&values[2],
|
||||
&step))
|
||||
goto have_framerate;
|
||||
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_STEP) {
|
||||
if (filter_framerate (&state->frmival, pi->range_values[0].val.value,
|
||||
pi->range_values[1].val.value,
|
||||
pi->range_values[2].val.value))
|
||||
} else if (range == SPA_PROP_RANGE_TYPE_STEP && n_values > 3) {
|
||||
if (filter_framerate (&state->frmival, &values[1],
|
||||
&values[2],
|
||||
&values[3]))
|
||||
goto have_framerate;
|
||||
} else if (pi->range_type == SPA_PROP_RANGE_TYPE_ENUM) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < pi->n_range_values; i++) {
|
||||
if (filter_framerate (&state->frmival, pi->range_values[i].val.value,
|
||||
pi->range_values[i].val.value,
|
||||
} else if (range == SPA_PROP_RANGE_TYPE_ENUM) {
|
||||
for (i = 1; i < n_values; i++) {
|
||||
if (filter_framerate (&state->frmival, &values[i],
|
||||
&values[i],
|
||||
&step))
|
||||
goto have_framerate;
|
||||
}
|
||||
|
|
@ -697,55 +690,43 @@ have_size:
|
|||
}
|
||||
|
||||
have_framerate:
|
||||
fmt->ranges[i].name = NULL;
|
||||
|
||||
if (state->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
|
||||
fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_ENUM;
|
||||
fmt->framerates[i].num = state->frmival.discrete.denominator;
|
||||
fmt->framerates[i].denom = state->frmival.discrete.numerator;
|
||||
fmt->ranges[i].val.size = sizeof (SpaFraction);
|
||||
fmt->ranges[i].val.value = &fmt->framerates[i];
|
||||
i++;
|
||||
prop->body.flags |= SPA_PROP_RANGE_TYPE_ENUM;
|
||||
spa_pod_builder_fraction (&b,
|
||||
state->frmival.discrete.denominator,
|
||||
state->frmival.discrete.numerator);
|
||||
state->frmival.index++;
|
||||
if (i == 16)
|
||||
break;
|
||||
} else if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
|
||||
state->frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
|
||||
fmt->framerates[0].num = state->frmival.stepwise.min.denominator;
|
||||
fmt->framerates[0].denom = state->frmival.stepwise.min.numerator;
|
||||
fmt->ranges[0].val.size = sizeof (SpaFraction);
|
||||
fmt->ranges[0].val.value = &fmt->framerates[0];
|
||||
fmt->framerates[1].num = state->frmival.stepwise.max.denominator;
|
||||
fmt->framerates[1].denom = state->frmival.stepwise.max.numerator;
|
||||
fmt->ranges[1].val.size = sizeof (SpaFraction);
|
||||
fmt->ranges[1].val.value = &fmt->framerates[1];
|
||||
spa_pod_builder_fraction (&b,
|
||||
state->frmival.stepwise.min.denominator,
|
||||
state->frmival.stepwise.min.numerator);
|
||||
spa_pod_builder_fraction (&b,
|
||||
state->frmival.stepwise.max.denominator,
|
||||
state->frmival.stepwise.max.numerator);
|
||||
|
||||
if (state->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
|
||||
fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_MIN_MAX;
|
||||
i = 2;
|
||||
prop->body.flags |= SPA_PROP_RANGE_TYPE_MIN_MAX;
|
||||
} else {
|
||||
fmt->infos[pi].range_type = SPA_PROP_RANGE_TYPE_STEP;
|
||||
fmt->framerates[2].num = state->frmival.stepwise.step.denominator;
|
||||
fmt->framerates[2].denom = state->frmival.stepwise.step.numerator;
|
||||
fmt->ranges[2].val.size = sizeof (SpaFraction);
|
||||
fmt->ranges[2].val.value = &fmt->framerates[2];
|
||||
i = 3;
|
||||
prop->body.flags |= SPA_PROP_RANGE_TYPE_STEP;
|
||||
spa_pod_builder_fraction (&b,
|
||||
state->frmival.stepwise.step.denominator,
|
||||
state->frmival.stepwise.step.numerator);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fmt->infos[pi].n_range_values = i;
|
||||
fmt->framerate = fmt->framerates[0];
|
||||
if (i > 1) {
|
||||
SPA_PROPS_INDEX_UNSET (&fmt->fmt.props, pi);
|
||||
}
|
||||
pi = ++fmt->fmt.props.n_prop_info;
|
||||
spa_pod_builder_pop (&b, &f[1]);
|
||||
spa_pod_builder_pop (&b, &f[0]);
|
||||
|
||||
*format = &state->format[0].fmt;
|
||||
*format = fmt;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
|
||||
spa_v4l2_set_format (SpaV4l2Source *this, SpaVideoInfo *f, bool try_only)
|
||||
{
|
||||
SpaV4l2State *state = &this->state[0];
|
||||
int cmd;
|
||||
|
|
@ -758,27 +739,27 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
|
|||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
info = find_format_info_by_media_type (f->fmt.media_type,
|
||||
f->fmt.media_subtype,
|
||||
f->format,
|
||||
info = find_format_info_by_media_type (f->media_type,
|
||||
f->media_subtype,
|
||||
f->info.raw.format,
|
||||
0);
|
||||
if (info == NULL) {
|
||||
spa_log_error (state->log, "v4l2: unknown media type %d %d %d", f->fmt.media_type,
|
||||
f->fmt.media_subtype, f->format);
|
||||
spa_log_error (state->log, "v4l2: unknown media type %d %d %d", f->media_type,
|
||||
f->media_subtype, f->info.raw.format);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fmt.fmt.pix.pixelformat = info->fourcc;
|
||||
fmt.fmt.pix.field = V4L2_FIELD_ANY;
|
||||
fmt.fmt.pix.width = f->size.width;
|
||||
fmt.fmt.pix.height = f->size.height;
|
||||
streamparm.parm.capture.timeperframe.numerator = f->framerate.denom;
|
||||
streamparm.parm.capture.timeperframe.denominator = f->framerate.num;
|
||||
fmt.fmt.pix.width = f->info.raw.size.width;
|
||||
fmt.fmt.pix.height = f->info.raw.size.height;
|
||||
streamparm.parm.capture.timeperframe.numerator = f->info.raw.framerate.denom;
|
||||
streamparm.parm.capture.timeperframe.denominator = f->info.raw.framerate.num;
|
||||
|
||||
spa_log_info (state->log, "v4l2: set %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat,
|
||||
fmt.fmt.pix.width, fmt.fmt.pix.height,
|
||||
streamparm.parm.capture.timeperframe.numerator,
|
||||
streamparm.parm.capture.timeperframe.denominator);
|
||||
streamparm.parm.capture.timeperframe.denominator,
|
||||
streamparm.parm.capture.timeperframe.numerator);
|
||||
|
||||
reqfmt = fmt;
|
||||
|
||||
|
|
@ -797,8 +778,8 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
|
|||
|
||||
spa_log_info (state->log, "v4l2: got %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat,
|
||||
fmt.fmt.pix.width, fmt.fmt.pix.height,
|
||||
streamparm.parm.capture.timeperframe.numerator,
|
||||
streamparm.parm.capture.timeperframe.denominator);
|
||||
streamparm.parm.capture.timeperframe.denominator,
|
||||
streamparm.parm.capture.timeperframe.numerator);
|
||||
|
||||
if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat ||
|
||||
reqfmt.fmt.pix.width != fmt.fmt.pix.width ||
|
||||
|
|
@ -808,6 +789,11 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
|
|||
if (try_only)
|
||||
return 0;
|
||||
|
||||
f->info.raw.size.width = fmt.fmt.pix.width;
|
||||
f->info.raw.size.height = fmt.fmt.pix.height;
|
||||
f->info.raw.framerate.num = streamparm.parm.capture.timeperframe.denominator;
|
||||
f->info.raw.framerate.denom = streamparm.parm.capture.timeperframe.numerator;
|
||||
|
||||
state->fmt = fmt;
|
||||
state->info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS |
|
||||
SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
|
||||
|
|
|
|||
|
|
@ -141,11 +141,11 @@ drawing_data_init (DrawingData *dd,
|
|||
SpaVideoTestSrc *this,
|
||||
char* data)
|
||||
{
|
||||
SpaFormatVideo *format = &this->current_format;
|
||||
SpaVideoInfo *format = &this->current_format;
|
||||
SpaRectangle *size = &format->info.raw.size;
|
||||
|
||||
if (format->format.media_type != SPA_MEDIA_TYPE_VIDEO ||
|
||||
format->format.media_subtype != SPA_MEDIA_SUBTYPE_RAW)
|
||||
if ((format->media_type != SPA_MEDIA_TYPE_VIDEO) ||
|
||||
(format->media_subtype != SPA_MEDIA_SUBTYPE_RAW))
|
||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
||||
switch (format->info.raw.format) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <spa/node.h>
|
||||
#include <spa/list.h>
|
||||
#include <spa/video/format.h>
|
||||
#include <spa/format-builder.h>
|
||||
#include <lib/props.h>
|
||||
|
||||
#define FRAMES_TO_TIME(this,f) ((this->current_format.info.raw.framerate.denom * (f) * SPA_NSEC_PER_SEC) / \
|
||||
|
|
@ -86,8 +87,8 @@ struct _SpaVideoTestSrc {
|
|||
SpaPortOutput *output;
|
||||
|
||||
bool have_format;
|
||||
SpaFormatVideo query_format;
|
||||
SpaFormatVideo current_format;
|
||||
SpaVideoInfo current_format;
|
||||
uint8_t format_buffer[1024];
|
||||
size_t bpp;
|
||||
|
||||
VTSBuffer buffers[MAX_BUFFERS];
|
||||
|
|
@ -430,6 +431,8 @@ spa_videotestsrc_node_port_enum_formats (SpaNode *node,
|
|||
SpaVideoTestSrc *this;
|
||||
SpaResult res;
|
||||
SpaFormat *fmt;
|
||||
uint8_t buffer[1024];
|
||||
SpaPODBuilder b = { buffer, sizeof (buffer), };
|
||||
|
||||
if (node == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -441,36 +444,39 @@ spa_videotestsrc_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
{
|
||||
int idx;
|
||||
static const uint32_t format_values[] = {
|
||||
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
|
||||
SPA_VIDEO_FORMAT_RGB,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_ENUM, 2,
|
||||
SPA_VIDEO_FORMAT_RGB,
|
||||
SPA_VIDEO_FORMAT_UYVY,
|
||||
};
|
||||
static const SpaPropRangeInfo format_range[] = {
|
||||
{ "RGB", { sizeof (uint32_t), &format_values[0] } },
|
||||
{ "UYVY", { sizeof (uint32_t), &format_values[1] } },
|
||||
};
|
||||
SpaPropInfo *info;
|
||||
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&this->query_format);
|
||||
|
||||
idx = spa_props_index_for_id (&this->query_format.format.props, SPA_PROP_ID_VIDEO_FORMAT);
|
||||
info = (SpaPropInfo *) &this->query_format.format.props.prop_info[idx];
|
||||
|
||||
info->n_range_values = SPA_N_ELEMENTS (format_range);
|
||||
info->range_values = format_range;
|
||||
SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE,
|
||||
320, 240,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, 1,
|
||||
INT32_MAX, INT32_MAX,
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, 25, 1,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
0, 1,
|
||||
INT32_MAX, 1,
|
||||
0), SpaFormat);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
|
||||
if ((res = spa_format_filter (&this->query_format.format, filter, &fmt)) != SPA_RESULT_OK)
|
||||
b.data = this->format_buffer;
|
||||
b.size = sizeof (this->format_buffer);
|
||||
b.offset = 0;
|
||||
|
||||
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
|
||||
return res;
|
||||
|
||||
*format = fmt;
|
||||
*format = SPA_MEMBER (this->format_buffer, 0, SpaFormat);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -561,6 +567,7 @@ spa_videotestsrc_node_port_get_format (SpaNode *node,
|
|||
const SpaFormat **format)
|
||||
{
|
||||
SpaVideoTestSrc *this;
|
||||
SpaPODBuilder b = { NULL, };
|
||||
|
||||
if (node == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -573,7 +580,24 @@ spa_videotestsrc_node_port_get_format (SpaNode *node,
|
|||
if (!this->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = &this->current_format.format;
|
||||
b.data = this->format_buffer;
|
||||
b.size = sizeof (this->format_buffer);
|
||||
|
||||
*format = SPA_MEMBER (b.data, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
|
||||
this->current_format.info.raw.format,
|
||||
SPA_POD_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_ID_VIDEO_SIZE, SPA_POD_TYPE_RECTANGLE,
|
||||
this->current_format.info.raw.size.width,
|
||||
this->current_format.info.raw.size.height,
|
||||
SPA_POD_PROP_FLAG_READWRITE,
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION,
|
||||
this->current_format.info.raw.framerate.num,
|
||||
this->current_format.info.raw.framerate.denom,
|
||||
SPA_POD_PROP_FLAG_READWRITE,
|
||||
0), SpaFormat);
|
||||
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <spa/node.h>
|
||||
#include <spa/list.h>
|
||||
#include <spa/audio/format.h>
|
||||
#include <spa/format-builder.h>
|
||||
#include <lib/props.h>
|
||||
|
||||
#define MAX_BUFFERS 16
|
||||
|
|
@ -79,8 +80,7 @@ struct _SpaVolume {
|
|||
SpaNodeEventCallback event_cb;
|
||||
void *user_data;
|
||||
|
||||
SpaFormatAudio query_format;
|
||||
SpaFormatAudio current_format;
|
||||
SpaAudioInfo current_format;
|
||||
|
||||
SpaVolumePort in_ports[1];
|
||||
SpaVolumePort out_ports[1];
|
||||
|
|
@ -291,6 +291,10 @@ spa_volume_node_port_enum_formats (SpaNode *node,
|
|||
unsigned int index)
|
||||
{
|
||||
SpaVolume *this;
|
||||
SpaResult res;
|
||||
SpaFormat *fmt;
|
||||
uint8_t buffer[1024];
|
||||
SpaPODBuilder b = { buffer, sizeof (buffer), };
|
||||
|
||||
if (node == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -302,14 +306,34 @@ spa_volume_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&this->query_format);
|
||||
fmt = SPA_MEMBER (buffer, spa_pod_builder_format (&b,
|
||||
SPA_MEDIA_TYPE_AUDIO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_AUDIO_FORMAT, SPA_POD_TYPE_INT,
|
||||
SPA_AUDIO_FORMAT_S16,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_ENUM, 2,
|
||||
SPA_AUDIO_FORMAT_S16,
|
||||
SPA_AUDIO_FORMAT_S32,
|
||||
SPA_PROP_ID_AUDIO_RATE, SPA_POD_TYPE_INT,
|
||||
44100,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, INT32_MAX,
|
||||
SPA_PROP_ID_AUDIO_CHANNELS, SPA_POD_TYPE_INT,
|
||||
2,
|
||||
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, INT32_MAX,
|
||||
0), SpaFormat);
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = &this->query_format.format;
|
||||
|
||||
if ((res = spa_format_filter (fmt, filter, NULL)) != SPA_RESULT_OK)
|
||||
return res;
|
||||
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -405,7 +429,7 @@ spa_volume_node_port_get_format (SpaNode *node,
|
|||
if (!port->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = &this->current_format.format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ struct _SpaXvSink {
|
|||
SpaNodeEventCallback event_cb;
|
||||
void *user_data;
|
||||
|
||||
SpaFormatVideo format[2];
|
||||
SpaFormat *current_format;
|
||||
bool have_format;
|
||||
SpaVideoInfo current_format;
|
||||
|
||||
SpaPortInfo info;
|
||||
SpaXvState state;
|
||||
|
|
@ -304,14 +304,11 @@ spa_xv_sink_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
switch (index) {
|
||||
case 0:
|
||||
spa_format_video_init (SPA_MEDIA_TYPE_VIDEO,
|
||||
SPA_MEDIA_SUBTYPE_RAW,
|
||||
&this->format[0]);
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = &this->format[0].format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -325,8 +322,7 @@ spa_xv_sink_node_port_set_format (SpaNode *node,
|
|||
{
|
||||
SpaXvSink *this;
|
||||
SpaResult res;
|
||||
SpaFormat *f, *tf;
|
||||
size_t fs;
|
||||
SpaVideoInfo info;
|
||||
|
||||
if (node == NULL || format == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -337,29 +333,25 @@ spa_xv_sink_node_port_set_format (SpaNode *node,
|
|||
return SPA_RESULT_INVALID_PORT;
|
||||
|
||||
if (format == NULL) {
|
||||
this->current_format = NULL;
|
||||
this->have_format = false;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
if (format->media_type == SPA_MEDIA_TYPE_VIDEO) {
|
||||
if (format->media_subtype == SPA_MEDIA_SUBTYPE_RAW) {
|
||||
if ((res = spa_format_video_parse (format, &this->format[0]) < 0))
|
||||
if ((res = spa_format_video_parse (format, &info) < 0))
|
||||
return res;
|
||||
|
||||
f = &this->format[0].format;
|
||||
tf = &this->format[1].format;
|
||||
fs = sizeof (SpaVideoFormat);
|
||||
} else
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
} else
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
if (spa_xv_set_format (this, f, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0)
|
||||
if (spa_xv_set_format (this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0)
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||
memcpy (tf, f, fs);
|
||||
this->current_format = tf;
|
||||
this->current_format = info;
|
||||
this->have_format = true;
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
@ -381,10 +373,10 @@ spa_xv_sink_node_port_get_format (SpaNode *node,
|
|||
if (!CHECK_PORT (this, direction, port_id))
|
||||
return SPA_RESULT_INVALID_PORT;
|
||||
|
||||
if (this->current_format == NULL)
|
||||
if (!this->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = this->current_format;
|
||||
*format = NULL;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ spa_xv_open (SpaXvSink *this)
|
|||
}
|
||||
|
||||
static int
|
||||
spa_xv_set_format (SpaXvSink *this, SpaFormat *format, bool try_only)
|
||||
spa_xv_set_format (SpaXvSink *this, SpaVideoInfo *info, bool try_only)
|
||||
{
|
||||
if (spa_xv_open (this) < 0)
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -28,32 +28,110 @@
|
|||
#include <spa/node.h>
|
||||
#include <spa/loop.h>
|
||||
#include <spa/video/format.h>
|
||||
#include <spa/format-builder.h>
|
||||
#include <lib/debug.h>
|
||||
#include <lib/props.h>
|
||||
#include <lib/prop-builder.h>
|
||||
#include <lib/video-raw.h>
|
||||
#include <lib/mapper.h>
|
||||
|
||||
#if 0
|
||||
/* { video/raw,
|
||||
* format: (int 1) { 1 2 },
|
||||
* size: (rect (320 240)) { (1 1) (MAX MAX) },
|
||||
* framerate: (frac (25 1)) { (0 1) (MAX 1) },
|
||||
*/
|
||||
|
||||
spa_build (SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_VIDEO_FORMAT, SPA_PROP_TYPE_INT,
|
||||
SPA_VIDEO_FORMAT_I420
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_PROP_RANGE_ENUM, 2,
|
||||
SPA_VIDEO_FORMAT_I420,
|
||||
SPA_VIDEO_FORMAT_YUY2,
|
||||
SPA_PROP_ID_VIDEO_SIZE , SPA_PROP_TYPE_RECTANGLE,
|
||||
320, 240,
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_PROP_RANGE_MIN_MAX,
|
||||
1, 1,
|
||||
INT32_MAX, INT32_MAX,
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE, SPA_PROP_TYPE_FRACTION, 25, 1,
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_PROP_RANGE_MIN_MAX,
|
||||
0, 1,
|
||||
INT32_MAX, 1,
|
||||
0);
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
SpaPropBuilder b;
|
||||
SpaPropBuilderInfo i[10];
|
||||
SpaPropBuilderRange r[10];
|
||||
SpaFormatVideo *f;
|
||||
SpaPODBuilder b = { NULL, };
|
||||
SpaPODFrame frame[4];
|
||||
uint8_t buffer[1024];
|
||||
SpaFormat *fmt;
|
||||
off_t o;
|
||||
|
||||
spa_prop_builder_init (&b, sizeof (SpaFormatVideo), offsetof (SpaFormatVideo, format.props));
|
||||
b.data = buffer;
|
||||
b.size = 1024;
|
||||
|
||||
spa_format_video_builder_add (&b, &i[0], SPA_PROP_ID_VIDEO_FORMAT, offsetof (SpaFormatVideo, info.raw));
|
||||
spa_format_video_builder_add_range (&b, &r[0], SPA_VIDEO_FORMAT_I420);
|
||||
spa_format_video_builder_add_range (&b, &r[1], SPA_VIDEO_FORMAT_YV12);
|
||||
fmt = SPA_MEMBER (buffer, spa_pod_builder_push_format (&b, &frame[0],
|
||||
SPA_MEDIA_TYPE_VIDEO,
|
||||
SPA_MEDIA_SUBTYPE_RAW), SpaFormat);
|
||||
spa_pod_builder_push_prop (&b, &frame[1],
|
||||
SPA_PROP_ID_VIDEO_FORMAT,
|
||||
SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE);
|
||||
spa_pod_builder_int (&b, SPA_VIDEO_FORMAT_I420);
|
||||
spa_pod_builder_int (&b, SPA_VIDEO_FORMAT_I420);
|
||||
spa_pod_builder_int (&b, SPA_VIDEO_FORMAT_YUY2);
|
||||
spa_pod_builder_pop (&b, &frame[1]);
|
||||
|
||||
b.dest = alloca (b.size);
|
||||
f = spa_prop_builder_finish (&b);
|
||||
f->format.media_type = SPA_MEDIA_TYPE_VIDEO;
|
||||
f->format.media_subtype = SPA_MEDIA_SUBTYPE_RAW;
|
||||
SpaRectangle size_min_max[] = { { 1, 1 }, { INT32_MAX, INT32_MAX } };
|
||||
spa_pod_builder_push_prop (&b, &frame[1],
|
||||
SPA_PROP_ID_VIDEO_SIZE,
|
||||
SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE);
|
||||
spa_pod_builder_rectangle (&b, 320, 240);
|
||||
spa_pod_builder_raw (&b, size_min_max, sizeof(size_min_max), false);
|
||||
spa_pod_builder_pop (&b, &frame[1]);
|
||||
|
||||
spa_debug_format (&f->format);
|
||||
SpaFraction rate_min_max[] = { { 0, 1 }, { INT32_MAX, 1 } };
|
||||
spa_pod_builder_push_prop (&b, &frame[1],
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE,
|
||||
SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE);
|
||||
spa_pod_builder_fraction (&b, 25, 1);
|
||||
spa_pod_builder_raw (&b, rate_min_max, sizeof(rate_min_max), false);
|
||||
spa_pod_builder_pop (&b, &frame[1]);
|
||||
|
||||
spa_pod_builder_pop (&b, &frame[0]);
|
||||
|
||||
spa_debug_pod (&fmt->obj.pod);
|
||||
|
||||
memset (&b, 0, sizeof(b));
|
||||
b.data = buffer;
|
||||
b.size = 1024;
|
||||
|
||||
o = spa_pod_builder_format (&b, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
|
||||
SPA_VIDEO_FORMAT_I420,
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_RANGE_ENUM, 2,
|
||||
SPA_VIDEO_FORMAT_I420,
|
||||
SPA_VIDEO_FORMAT_YUY2,
|
||||
SPA_PROP_ID_VIDEO_SIZE , SPA_POD_TYPE_RECTANGLE,
|
||||
320, 240,
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, 1,
|
||||
INT32_MAX, INT32_MAX,
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_TYPE_FRACTION, 25, 1,
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
0, 1,
|
||||
INT32_MAX, 1,
|
||||
0);
|
||||
|
||||
printf ("%zd\n", o);
|
||||
fmt = SPA_MEMBER (buffer, o, SpaFormat);
|
||||
printf ("%d %d\n", fmt->media_type, fmt->media_subtype);
|
||||
spa_debug_pod (&fmt->obj.pod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,10 +143,10 @@ main (int argc, char *argv[])
|
|||
spa_pod_builder_int (&b, 42);
|
||||
spa_pod_builder_pop (&b, &frame[1]);
|
||||
|
||||
SpaRectangle def = { 320, 240 }, sizes[] = { { 0, 0 }, { 1024, 1024} };
|
||||
SpaRectangle sizes[] = { { 0, 0 }, { 1024, 1024} };
|
||||
spa_pod_builder_push_prop (&b, &frame[1],
|
||||
3, SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE);
|
||||
spa_pod_builder_rectangle (&b, &def);
|
||||
spa_pod_builder_rectangle (&b, 320, 240);
|
||||
spa_pod_builder_raw (&b, sizes, sizeof (sizes), false);
|
||||
spa_pod_builder_pop (&b, &frame[1]);
|
||||
|
||||
|
|
@ -157,9 +157,8 @@ main (int argc, char *argv[])
|
|||
spa_pod_builder_float (&b, 4.0);
|
||||
spa_pod_builder_double (&b, 3.14);
|
||||
spa_pod_builder_string (&b, "test123", strlen ("test123"));
|
||||
spa_pod_builder_rectangle (&b, &def);
|
||||
SpaFraction f = { 25, 1 };
|
||||
spa_pod_builder_fraction (&b, &f);
|
||||
spa_pod_builder_rectangle (&b, 320, 240);
|
||||
spa_pod_builder_fraction (&b, 25, 1);
|
||||
spa_pod_builder_push_array (&b, &frame[3]);
|
||||
spa_pod_builder_int (&b, 4);
|
||||
spa_pod_builder_int (&b, 5);
|
||||
|
|
@ -169,7 +168,7 @@ main (int argc, char *argv[])
|
|||
spa_pod_builder_pop (&b, &frame[1]);
|
||||
spa_pod_builder_pop (&b, &frame[0]);
|
||||
|
||||
print_value (obj->size, obj->type, SPA_POD_BODY (obj), 0, 0);
|
||||
spa_debug_pod (obj);
|
||||
|
||||
SpaPODProp *p = spa_pod_object_body_find_prop (SPA_POD_BODY (obj), obj->size, 4);
|
||||
printf ("%d %d\n", p->body.key, p->body.flags);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue