Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link with apt-X/apt-X HD library by pali.rohar #356

Closed
wants to merge 1 commit into from
Closed

Conversation

arkq
Copy link
Owner

@arkq arkq commented Aug 3, 2020

This PR requires pali/libopenaptx#5

Relates to PRs: #253
Relates to issues: #92, #241, #242, #355

rodan
rodan previously approved these changes Aug 4, 2020
Copy link

@rodan rodan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5/5 would patch again.
works as a source for FiiO Q5s over a aptX-HD connection

@pali
Copy link

pali commented Aug 7, 2020

Here is my alternative implementation which does not require any changes to libopenaptx and bluealsa would use native libopenaptx API. I have not tested it.

diff --git a/configure.ac b/configure.ac
index 44250d8..6caec6c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -96,11 +96,22 @@ AM_COND_IF([ENABLE_AAC], [
 	AC_DEFINE([ENABLE_AAC], [1], [Define to 1 if AAC is enabled.])
 ])
 
+AC_ARG_WITH([libopenaptx],
+	[AS_HELP_STRING([--with-libopenaptx], [use libopenaptx from https://github.com/pali/libopenaptx for apt-X (HD)])])
+AM_CONDITIONAL([WITH_LIBOPENAPTX], [test "x$with_libopenaptx" = "xyes"])
+AM_COND_IF([WITH_LIBOPENAPTX], [
+	AC_DEFINE([WITH_LIBOPENAPTX], [1], [Define to 1 if libopenaptx is used.])
+])
+
 AC_ARG_ENABLE([aptx],
 	[AS_HELP_STRING([--enable-aptx], [enable apt-X encoding support])])
 AM_CONDITIONAL([ENABLE_APTX], [test "x$enable_aptx" = "xyes"])
 AM_COND_IF([ENABLE_APTX], [
-	PKG_CHECK_MODULES([APTX], [openaptx >= 1.0.0])
+	AM_COND_IF([WITH_LIBOPENAPTX], [
+		PKG_CHECK_MODULES([APTX], [libopenaptx])
+	], [
+		PKG_CHECK_MODULES([APTX], [openaptx >= 1.0.0])
+	])
 	AC_DEFINE([ENABLE_APTX], [1], [Define to 1 if apt-X is enabled.])
 ])
 
@@ -108,7 +119,11 @@ AC_ARG_ENABLE([aptx_hd],
 	[AS_HELP_STRING([--enable-aptx-hd], [enable apt-X HD encoding support])])
 AM_CONDITIONAL([ENABLE_APTX_HD], [test "x$enable_aptx_hd" = "xyes"])
 AM_COND_IF([ENABLE_APTX_HD], [
-	PKG_CHECK_MODULES([APTX_HD], [openaptxhd >= 1.0.0])
+	AM_COND_IF([WITH_LIBOPENAPTX], [
+		PKG_CHECK_MODULES([APTX_HD], [libopenaptx])
+	], [
+		PKG_CHECK_MODULES([APTX_HD], [openaptxhd >= 1.0.0])
+	])
 	AC_DEFINE([ENABLE_APTX_HD], [1], [Define to 1 if apt-X HD is enabled.])
 ])
 
diff --git a/src/a2dp-audio.c b/src/a2dp-audio.c
index 62a7461..65d6f45 100644
--- a/src/a2dp-audio.c
+++ b/src/a2dp-audio.c
@@ -1538,6 +1538,15 @@ static void *a2dp_source_aptx(struct ba_transport *t) {
 		.t_locked = !ba_transport_pthread_cleanup_lock(t),
 	};
 
+#if WITH_LIBOPENAPTX
+	struct aptx_context *handle = aptx_init(0);
+	if (handle == NULL) {
+		error("Couldn't initialize apt-X encoder");
+		goto fail_init;
+	}
+
+	pthread_cleanup_push(PTHREAD_CLEANUP(aptx_finish), handle);
+#else
 	APTXENC handle = malloc(SizeofAptxbtenc());
 	pthread_cleanup_push(PTHREAD_CLEANUP(free), handle);
 
@@ -1545,6 +1554,7 @@ static void *a2dp_source_aptx(struct ba_transport *t) {
 		error("Couldn't initialize apt-X encoder: %s", strerror(errno));
 		goto fail_init;
 	}
+#endif
 
 	ffb_uint8_t bt = { 0 };
 	ffb_int16_t pcm = { 0 };
@@ -1591,6 +1601,17 @@ static void *a2dp_source_aptx(struct ba_transport *t) {
 			 * the socket MTU, so such a transfer should be most efficient. */
 			while (input_len >= aptx_pcm_samples && output_len >= aptx_code_len) {
 
+#if WITH_LIBOPENAPTX
+				#define PCM(val) 0, (val & 0xFF), ((val >> 8) & 0xFF)
+				unsigned char pcm_s24[24] = { PCM(input[0]), PCM(input[1]), PCM(input[2]), PCM(input[3]), PCM(input[4]), PCM(input[5]), PCM(input[6]), PCM(input[7]) };
+				#undef PCM
+				size_t written;
+
+				if (aptx_encode(handle, pcm_s24, sizeof(pcm_s24), bt.tail, aptx_code_len, &written) != sizeof(pcm_s24) || written != aptx_code_len) {
+					error("Apt-X encoding error");
+					break;
+				}
+#else
 				int32_t pcm_l[4] = { input[0], input[2], input[4], input[6] };
 				int32_t pcm_r[4] = { input[1], input[3], input[5], input[7] };
 
@@ -1598,6 +1619,7 @@ static void *a2dp_source_aptx(struct ba_transport *t) {
 					error("Apt-X encoding error: %s", strerror(errno));
 					break;
 				}
+#endif
 
 				input += 4 * channels;
 				input_len -= 4 * channels;
@@ -1661,6 +1683,15 @@ static void *a2dp_source_aptx_hd(struct ba_transport *t) {
 		.t_locked = !ba_transport_pthread_cleanup_lock(t),
 	};
 
+#if WITH_LIBOPENAPTX
+	struct aptx_context *handle = aptx_init(1);
+	if (handle == NULL) {
+		error("Couldn't initialize apt-X HD encoder");
+		goto fail_init;
+	}
+
+	pthread_cleanup_push(PTHREAD_CLEANUP(aptx_finish), handle);
+#else
 	APTXENC handle = malloc(SizeofAptxhdbtenc());
 	pthread_cleanup_push(PTHREAD_CLEANUP(free), handle);
 
@@ -1668,6 +1699,7 @@ static void *a2dp_source_aptx_hd(struct ba_transport *t) {
 		error("Couldn't initialize apt-X HD encoder: %s", strerror(errno));
 		goto fail_init;
 	}
+#endif
 
 	ffb_uint8_t bt = { 0 };
 	ffb_int16_t pcm = { 0 };
@@ -1725,6 +1757,17 @@ static void *a2dp_source_aptx_hd(struct ba_transport *t) {
 			 * the socket MTU, so such a transfer should be most efficient. */
 			while (input_len >= aptx_pcm_samples && output_len >= aptx_code_len) {
 
+#if WITH_LIBOPENAPTX
+				#define PCM(val) 0, (val & 0xFF), ((val >> 8) & 0xFF)
+				unsigned char pcm_s24[24] = { PCM(input[0]), PCM(input[1]), PCM(input[2]), PCM(input[3]), PCM(input[4]), PCM(input[5]), PCM(input[6]), PCM(input[7]) };
+				#undef PCM
+				size_t written;
+
+				if (aptx_encode(handle, pcm_s24, sizeof(pcm_s24), bt.tail, aptx_code_len, &written) != sizeof(pcm_s24) || written != aptx_code_len) {
+					error("Apt-X HD encoding error");
+					break;
+				}
+#else
 				int32_t pcm_l[4] = { input[0] << 8, input[2] << 8, input[4] << 8, input[6] << 8 };
 				int32_t pcm_r[4] = { input[1] << 8, input[3] << 8, input[5] << 8, input[7] << 8 };
 				uint32_t code[2];
@@ -1740,6 +1783,7 @@ static void *a2dp_source_aptx_hd(struct ba_transport *t) {
 				bt.tail[3] = ((uint8_t *)code)[6];
 				bt.tail[4] = ((uint8_t *)code)[5];
 				bt.tail[5] = ((uint8_t *)code)[4];
+#endif
 
 				input += 4 * channels;
 				input_len -= 4 * channels;

@rodan
Copy link

rodan commented Oct 14, 2020

hello!

@arkq how do you want to proceed with adding stable support for aptx via @pali 's libopenaptx?

your previous patch no longer works with bluez-alsa-3.0.0:

/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0/src/utils.c: In function 'aptxbtenc_destroy_free':
/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0/src/utils.c:582:6: error: 'aptxbtenc_destroy' undeclared (first use in this function); did you mean 'aptxbtenc_destroy_free'?
582 | if (aptxbtenc_destroy != NULL)
| ^~~~~~~~~~~~~~~~~
| aptxbtenc_destroy_free
/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0/src/utils.c:582:6: note: each undeclared identifier is reported only once for each function it appears in
/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0/src/utils.c:583:3: warning: implicit declaration of function 'aptxbtenc_destroy'; did you mean 'aptxbtenc_destroy_free'? [-Wimplicit-function-declaration]
583 | aptxbtenc_destroy(enc);
| ^~~~~~~~~~~~~~~~~
| aptxbtenc_destroy_free
/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0/src/utils.c: In function 'aptxhdbtenc_destroy_free':
/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0/src/utils.c:594:6: error: 'aptxhdbtenc_destroy' undeclared (first use in this function); did you mean 'aptxhdbtenc_destroy_free'?
594 | if (aptxhdbtenc_destroy != NULL)
| ^~~~~~~~~~~~~~~~~~~
| aptxhdbtenc_destroy_free
/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0/src/utils.c:595:3: warning: implicit declaration of function 'aptxhdbtenc_destroy'; did you mean 'aptxhdbtenc_destroy_free'? [-Wimplicit-function-declaration]
595 | aptxhdbtenc_destroy(enc);
| ^~~~~~~~~~~~~~~~~~~
| aptxhdbtenc_destroy_free
distcc[309] ERROR: compile /dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0/src/utils.c on localhost failed
make[3]: *** [Makefile:630: utils.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[3]: Leaving directory '/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0-abi_x86_64.amd64/src'
make[2]: *** [Makefile:682: all-recursive] Error 1
make[2]: Leaving directory '/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0-abi_x86_64.amd64/src'
make[1]: *** [Makefile:442: all-recursive] Error 1
make[1]: Leaving directory '/dev/shm/portage/media-sound/bluez-alsa-3.0.0/work/bluez-alsa-3.0.0-abi_x86_64.amd64'
make: *** [Makefile:374: all] Error 2

I configured --with-libopenaptx --enable-aptx --enable-aptx-hd

@arkq
Copy link
Owner Author

arkq commented Dec 31, 2020

For usage with pali/libopenaptx please use patch from this comment, or create a wrapper for libopenaptx which will use aptX Adaptive API (library shall provide aptxbtenc_destroy() function for releasing resources). Alternatively, simply use openaptx with FFmpeg as a back-end.

@arkq arkq closed this Dec 31, 2020
@arkq arkq deleted the libopenaptx branch December 31, 2020 15:33
arkq added a commit that referenced this pull request Jan 24, 2021
arkq added a commit that referenced this pull request Jan 26, 2021
@arkq
Copy link
Owner Author

arkq commented Jan 27, 2021

If anyone is interested, with commit c2bcc93 it is possible to link bluez-alsa with libopenaptx (decoding and encoding). In order to enable it, use --enable-aptx --enable-aptx-hd --with-libopenaptx during configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants