summaryrefslogtreecommitdiff
blob: f1fc4601a23ac60a1a53ef21be920038e4a7b5ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
From cc3419daf60159394cd310c2405a78775b3f84db Mon Sep 17 00:00:00 2001
From: Sanchayan Maity <sanchayan@asymptotic.io>
Date: Thu, 24 Feb 2022 20:28:23 +0530
Subject: [PATCH] rtp: ldac: Set frame count information in payload

The RTP payload seems to be required as it carries the frame count
information. Also, gst_rtp_base_payload_allocate_output_buffer had
the second argument incorrect.

Strangely some devices like Shanling MP4 and Sony XM3 would still
work without this while some like the Sony XM4 do not.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1797>
---
 .../docs/gst_plugins_cache.json               |  2 +-
 .../gst-plugins-good/gst/rtp/gstrtpldacpay.c  | 63 ++++++++++++++++++-
 .../gst-plugins-good/gst/rtp/gstrtpldacpay.h  |  1 +
 3 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/docs/gst_plugins_cache.json b/docs/gst_plugins_cache.json
index 88bff47243..003546d59d 100644
--- a/docs/gst_plugins_cache.json
+++ b/docs/gst_plugins_cache.json
@@ -14678,7 +14678,7 @@
                 "long-name": "RTP packet payloader",
                 "pad-templates": {
                     "sink": {
-                        "caps": "audio/x-ldac:\n       channels: [ 1, 2 ]\n           rate: { (int)44100, (int)48000, (int)88200, (int)96000 }\n",
+                        "caps": "audio/x-ldac:\n       channels: [ 1, 2 ]\n          eqmid: { (int)0, (int)1, (int)2 }\n           rate: { (int)44100, (int)48000, (int)88200, (int)96000 }\n",
                         "direction": "sink",
                         "presence": "always"
                     },
diff --git a/gst/rtp/gstrtpldacpay.c b/gst/rtp/gstrtpldacpay.c
index 2b14b746fe..aa30673e7e 100644
--- a/gst/rtp/gstrtpldacpay.c
+++ b/gst/rtp/gstrtpldacpay.c
@@ -48,7 +48,7 @@
 #include "gstrtpldacpay.h"
 #include "gstrtputils.h"
 
-#define GST_RTP_HEADER_LENGTH    12
+#define GST_RTP_LDAC_PAYLOAD_HEADER_SIZE 1
 /* MTU size required for LDAC A2DP streaming */
 #define GST_LDAC_MTU_REQUIRED    679
 
@@ -64,6 +64,7 @@ static GstStaticPadTemplate gst_rtp_ldac_pay_sink_factory =
 GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("audio/x-ldac, "
         "channels = (int) [ 1, 2 ], "
+        "eqmid = (int) { 0, 1, 2 }, "
         "rate = (int) { 44100, 48000, 88200, 96000 }")
     );
 
@@ -81,6 +82,38 @@ static gboolean gst_rtp_ldac_pay_set_caps (GstRTPBasePayload * payload,
 static GstFlowReturn gst_rtp_ldac_pay_handle_buffer (GstRTPBasePayload *
     payload, GstBuffer * buffer);
 
+/**
+ * gst_rtp_ldac_pay_get_num_frames
+ * @eqmid: Encode Quality Mode Index
+ * @channels: Number of channels
+ *
+ * Returns: Number of LDAC frames per packet.
+ */
+static guint8
+gst_rtp_ldac_pay_get_num_frames (gint eqmid, gint channels)
+{
+  g_assert (channels == 1 || channels == 2);
+
+  switch (eqmid) {
+      /* Encode setting for High Quality */
+    case 0:
+      return 4 / channels;
+      /* Encode setting for Standard Quality */
+    case 1:
+      return 6 / channels;
+      /* Encode setting for Mobile use Quality */
+    case 2:
+      return 12 / channels;
+    default:
+      break;
+  }
+
+  g_assert_not_reached ();
+
+  /* If assertion gets compiled out */
+  return 6 / channels;
+}
+
 static void
 gst_rtp_ldac_pay_class_init (GstRtpLdacPayClass * klass)
 {
@@ -115,7 +148,7 @@ gst_rtp_ldac_pay_set_caps (GstRTPBasePayload * payload, GstCaps * caps)
 {
   GstRtpLdacPay *ldacpay = GST_RTP_LDAC_PAY (payload);
   GstStructure *structure;
-  gint rate;
+  gint channels, eqmid, rate;
 
   if (GST_RTP_BASE_PAYLOAD_MTU (ldacpay) < GST_LDAC_MTU_REQUIRED) {
     GST_ERROR_OBJECT (ldacpay, "Invalid MTU %d, should be >= %d",
@@ -129,6 +162,18 @@ gst_rtp_ldac_pay_set_caps (GstRTPBasePayload * payload, GstCaps * caps)
     return FALSE;
   }
 
+  if (!gst_structure_get_int (structure, "channels", &channels)) {
+    GST_ERROR_OBJECT (ldacpay, "Failed to get audio rate from caps");
+    return FALSE;
+  }
+
+  if (!gst_structure_get_int (structure, "eqmid", &eqmid)) {
+    GST_ERROR_OBJECT (ldacpay, "Failed to get eqmid from caps");
+    return FALSE;
+  }
+
+  ldacpay->frame_count = gst_rtp_ldac_pay_get_num_frames (eqmid, channels);
+
   gst_rtp_base_payload_set_options (payload, "audio", TRUE, "X-GST-LDAC", rate);
 
   return gst_rtp_base_payload_set_outcaps (payload, NULL);
@@ -145,14 +190,26 @@ gst_rtp_ldac_pay_set_caps (GstRTPBasePayload * payload, GstCaps * caps)
 static GstFlowReturn
 gst_rtp_ldac_pay_handle_buffer (GstRTPBasePayload * payload, GstBuffer * buffer)
 {
+  GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
   GstRtpLdacPay *ldacpay = GST_RTP_LDAC_PAY (payload);
   GstBuffer *outbuf;
   GstClockTime outbuf_frame_duration, outbuf_pts;
+  guint8 *payload_data;
   gsize buf_sz;
 
   outbuf =
       gst_rtp_base_payload_allocate_output_buffer (GST_RTP_BASE_PAYLOAD
-      (ldacpay), GST_RTP_HEADER_LENGTH, 0, 0);
+      (ldacpay), GST_RTP_LDAC_PAYLOAD_HEADER_SIZE, 0, 0);
+
+  /* Get payload */
+  gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
+
+  /* Write header and copy data into payload */
+  payload_data = gst_rtp_buffer_get_payload (&rtp);
+  /* Upper 3 fragment bits not used, ref A2DP v13, 4.3.4 */
+  payload_data[0] = ldacpay->frame_count & 0x0f;
+
+  gst_rtp_buffer_unmap (&rtp);
 
   outbuf_pts = GST_BUFFER_PTS (buffer);
   outbuf_frame_duration = GST_BUFFER_DURATION (buffer);
diff --git a/gst/rtp/gstrtpldacpay.h b/gst/rtp/gstrtpldacpay.h
index 0865ce7ade..0134491752 100644
--- a/gst/rtp/gstrtpldacpay.h
+++ b/gst/rtp/gstrtpldacpay.h
@@ -42,6 +42,7 @@ typedef struct _GstRtpLdacPayClass GstRtpLdacPayClass;
 
 struct _GstRtpLdacPay {
   GstRTPBasePayload base;
+  guint8 frame_count;
 };
 
 struct _GstRtpLdacPayClass {
-- 
GitLab