Commit 5be2e3a3 authored by Benjamin Berg's avatar Benjamin Berg
Browse files

wfd: Add audio codec parameter parsing

parent 19faa7db
......@@ -6,6 +6,7 @@ wfd_server_sources = [
'wfd-params.c',
'wfd-resolution.c',
'wfd-server.c',
'wfd-audio-codec.c',
'wfd-video-codec.c',
]
......@@ -26,4 +27,4 @@ wfd_server = static_library(
'wfd-server',
wfd_server_sources,
dependencies: wfd_server_deps,
)
)
\ No newline at end of file
#include "wfd-audio-codec.h"
G_DEFINE_BOXED_TYPE (WfdAudioCodec, wfd_audio_codec, wfd_audio_codec_ref, wfd_audio_codec_unref)
/**
* wfd_audio_codec_new:
*
* Creates a new #WfdAudioCodec.
*
* Returns: (transfer full): A newly created #WfdAudioCodec
*/
WfdAudioCodec *
wfd_audio_codec_new (void)
{
WfdAudioCodec *self;
self = g_slice_new0 (WfdAudioCodec);
self->ref_count = 1;
return self;
}
/**
* wfd_audio_codec_copy:
* @self: a #WfdAudioCodec
*
* Makes a deep copy of a #WfdAudioCodec.
*
* Returns: (transfer full): A newly created #WfdAudioCodec with the same
* contents as @self
*/
WfdAudioCodec *
wfd_audio_codec_copy (WfdAudioCodec *self)
{
WfdAudioCodec *copy;
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (self->ref_count, NULL);
copy = wfd_audio_codec_new ();
return copy;
}
static void
wfd_audio_codec_free (WfdAudioCodec *self)
{
g_assert (self);
g_assert_cmpint (self->ref_count, ==, 0);
g_slice_free (WfdAudioCodec, self);
}
/**
* wfd_audio_codec_ref:
* @self: A #WfdAudioCodec
*
* Increments the reference count of @self by one.
*
* Returns: (transfer none): @self
*/
WfdAudioCodec *
wfd_audio_codec_ref (WfdAudioCodec *self)
{
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (self->ref_count, NULL);
g_atomic_int_inc (&self->ref_count);
return self;
}
/**
* wfd_audio_codec_unref:
* @self: (transfer none): A #WfdAudioCodec
*
* Decrements the reference count of @self by one, freeing the structure when
* the reference count reaches zero.
*/
void
wfd_audio_codec_unref (WfdAudioCodec *self)
{
g_return_if_fail (self);
g_return_if_fail (self->ref_count);
if (g_atomic_int_dec_and_test (&self->ref_count))
wfd_audio_codec_free (self);
}
WfdAudioCodec*
wfd_audio_codec_new_from_desc (const gchar *descr)
{
g_autoptr(WfdAudioCodec) res;
g_auto(GStrv) tokens = NULL;
tokens = g_strsplit (descr, " ", 3);
if (g_strv_length (tokens) < 3)
return NULL;
res = wfd_audio_codec_new ();
if (g_str_equal (tokens[0], "LPCM"))
res->type = WFD_AUDIO_LPCM;
else if (g_str_equal (tokens[0], "AAC"))
res->type = WFD_AUDIO_AAC;
else if (g_str_equal (tokens[0], "AC3"))
res->type = WFD_AUDIO_AC3;
else
return NULL;
res->modes = g_ascii_strtoll (tokens[1], NULL, 16);
res->latency_ms = g_ascii_strtoull (tokens[2], NULL, 16) * 5;
return g_steal_pointer (&res);
}
void
wfd_audio_codec_dump (WfdAudioCodec *self)
{
const gchar *type = "invalid";
switch (self->type)
{
case WFD_AUDIO_LPCM:
type = "LPCM";
break;
case WFD_AUDIO_AAC:
type = "AAC";
break;
case WFD_AUDIO_AC3:
type = "AC3";
break;
default:
g_assert_not_reached ();
}
g_debug ("WfdAudioCodec: %s, %" G_GUINT32_FORMAT ", latency: %d", type, self->modes, self->latency_ms);
}
#pragma once
#include <glib-object.h>
G_BEGIN_DECLS
#define WFD_TYPE_AUDIO_CODEC (wfd_audio_codec_get_type ())
typedef enum {
WFD_AUDIO_LPCM,
WFD_AUDIO_AAC,
WFD_AUDIO_AC3,
} WfdAudioCodecType;
typedef struct _WfdAudioCodec WfdAudioCodec;
struct _WfdAudioCodec
{
WfdAudioCodecType type;
guint32 modes;
guint latency_ms;
/*< private >*/
guint ref_count;
};
GType wfd_audio_codec_get_type (void) G_GNUC_CONST;
WfdAudioCodec *wfd_audio_codec_new (void);
WfdAudioCodec *wfd_audio_codec_copy (WfdAudioCodec *self);
WfdAudioCodec *wfd_audio_codec_ref (WfdAudioCodec *self);
void wfd_audio_codec_unref (WfdAudioCodec *self);
WfdAudioCodec *wfd_audio_codec_new_from_desc (const gchar *descr);
void wfd_audio_codec_dump (WfdAudioCodec *self);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (WfdAudioCodec, wfd_audio_codec_unref)
G_END_DECLS
......@@ -57,6 +57,8 @@ wfd_params_new (void)
basic_codec = wfd_video_codec_new_from_desc (7 << 3, "01 01 00000081 00000000 00000000 00 0000 0000 00 none none");
g_ptr_array_add (self->video_codecs, basic_codec);
self->audio_codecs = g_ptr_array_new_with_free_func ((GDestroyNotify) wfd_audio_codec_unref);
/* Set a default resolution (for testing purposes) */
self->selected_codec = wfd_video_codec_ref (basic_codec);
self->selected_resolution = wfd_resolution_copy (basic_codec->native);
......@@ -100,10 +102,20 @@ wfd_params_copy (WfdParams *self)
g_ptr_array_add (copy->video_codecs, new_codec);
}
for (guint i = 0; i < self->audio_codecs->len; i++)
{
WfdAudioCodec *codec = (WfdAudioCodec *) g_ptr_array_index (self->audio_codecs, i);
WfdAudioCodec *new_codec = wfd_audio_codec_copy (codec);
g_ptr_array_add (copy->audio_codecs, new_codec);
}
if (self->selected_codec)
copy->selected_codec = wfd_video_codec_copy (self->selected_codec);
if (self->selected_resolution)
copy->selected_resolution = wfd_resolution_copy (self->selected_resolution);
if (self->selected_audio_codec)
copy->selected_audio_codec = wfd_audio_codec_copy (self->selected_audio_codec);
return copy;
}
......@@ -122,8 +134,10 @@ wfd_params_free (WfdParams *self)
g_clear_pointer (&self->selected_codec, wfd_video_codec_unref);
g_clear_pointer (&self->selected_resolution, wfd_resolution_free);
g_clear_pointer (&self->selected_audio_codec, wfd_audio_codec_unref);
g_clear_pointer (&self->video_codecs, g_ptr_array_unref);
g_clear_pointer (&self->audio_codecs, g_ptr_array_unref);
g_clear_pointer (&self->edid, g_byte_array_unref);
g_clear_pointer (&self->profile, g_free);
......@@ -260,8 +274,35 @@ wfd_params_from_sink (WfdParams *self, const guint8 *body, gsize body_size)
}
else if (g_str_equal (option, "wfd_audio_codecs"))
{
/* TODO: Implement */
g_warning ("WfdParams: Audio codec parsing not yet implemented!");
g_auto(GStrv) codec_descriptors = NULL;
char **codec_descriptor;
/* Clear audio codecs to fill them up again. */
g_clear_pointer (&self->selected_audio_codec, wfd_audio_codec_unref);
g_ptr_array_unref (self->audio_codecs);
self->audio_codecs = g_ptr_array_new_with_free_func ((GDestroyNotify) wfd_audio_codec_unref);
if (g_str_equal (value, "none"))
continue;
codec_descriptors = g_strsplit (value, ",", 0);
for (codec_descriptor = codec_descriptors; *codec_descriptor; codec_descriptor++)
{
g_autoptr(WfdAudioCodec) codec = NULL;
g_strstrip (*codec_descriptor);
codec = wfd_audio_codec_new_from_desc (*codec_descriptor);
if (codec)
{
g_debug ("Add audio codec to params:");
wfd_audio_codec_dump (codec);
g_ptr_array_add (self->audio_codecs, g_steal_pointer (&codec));
}
else
{
g_warning ("WfdParams: Could not parse codec descriptor: %s", *codec_descriptor);
}
}
}
else if (g_str_equal (option, "wfd_display_edid"))
{
......
......@@ -2,6 +2,7 @@
#include <glib-object.h>
#include "wfd-video-codec.h"
#include "wfd-audio-codec.h"
G_BEGIN_DECLS
......@@ -23,8 +24,10 @@ struct _WfdParams
WfdVideoCodec *selected_codec;
WfdResolution *selected_resolution;
WfdAudioCodec *selected_audio_codec;
GPtrArray *video_codecs;
GPtrArray *audio_codecs;
};
typedef struct _WfdParams WfdParams;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment