Skip to content
Snippets Groups Projects
Commit c26e30a0 authored by Timo Teräs's avatar Timo Teräs
Browse files

main/omxplayer: update alsa player patch

- add support for live resampling using speexdsp
- fix few bugs
parent 7d850243
No related merge requests found
......@@ -2,14 +2,14 @@
pkgname=omxplayer
pkgver=0.20160206
_commitid=19efb03b881da0bcc70632eaf7f7292edcf33eeb
pkgrel=0
pkgrel=1
pkgdesc="Commandline OMX player for Raspberry Pi"
url="https://github.com/popcornmix/omxplayer"
arch="armhf"
license="GPLv2"
depends="ttf-freefont"
makedepends="linux-headers raspberrypi-dev ffmpeg-dev pcre-dev
boost-dev freetype-dev dbus-dev alsa-lib-dev"
boost-dev freetype-dev dbus-dev alsa-lib-dev speexdsp-dev"
install=""
subpackages="$pkgname-doc $pkgname-dbg"
source="omxplayer-$pkgver.tar.gz::https://github.com/popcornmix/omxplayer/archive/$_commitid.tar.gz
......@@ -39,9 +39,9 @@ build() {
cd "$_srcdir"
cat <<EOF > Makefile.include
INCLUDES:=-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux
INCLUDES+=$(pkg-config --cflags freetype2 dbus-1)
INCLUDES+=$(pkg-config --cflags freetype2 dbus-1 speexdsp)
LDFLAGS:=-L/opt/vc/lib -Wl,-rpath,/opt/vc/lib
LDFLAGS+=$(pkg-config --libs freetype2 dbus-1)
LDFLAGS+=$(pkg-config --libs freetype2 dbus-1 speexdsp)
STRIP:=echo
EOF
make omxplayer.bin omxplayer.1
......@@ -63,7 +63,7 @@ a900cdded87b7df503c6599ac43bd8de issue-260.patch
c858882036b9fb03859edf7ce4a1d942 issue-297.patch
d8f335e1dff4b34faf36c25ad2c2b881 fix-makefile.patch
9ebd96155288809fe0a657cf491e433f default-font.patch
24bc3d0db0fcbd547bec6df454937940 omxplayer-alsa.patch
930ff50f91bc2a7c24661b6313581868 omxplayer-alsa.patch
b4054a311d76aef91aa10bacd68bc9c4 omxplayer.initd
80e37e7ac04402808015084e26e6072d omxplayer.confd"
sha256sums="bfdcd411e759f7791ceace6c700b5ee6f5a6e8b34abbc261f01c32b8e71d559e omxplayer-0.20160206.tar.gz
......@@ -71,7 +71,7 @@ sha256sums="bfdcd411e759f7791ceace6c700b5ee6f5a6e8b34abbc261f01c32b8e71d559e om
389c97df4919a3fe4d115f092cb256246e33374150102f0e2cb9ce11456cadb1 issue-297.patch
799b0aba6aef8c665a685777cd912268315309d0d74ce76be5fdfd0dcffbb422 fix-makefile.patch
2bab3d05b12d730737220b8c0052498a34bbebc12b7beb8afb3c054beb0fb3bb default-font.patch
dd547f952cdc6d96f565694993817075803a05d4d16c6b51e982244f8980445c omxplayer-alsa.patch
2dedced50fd1d40aadade37651abfb1edeb36de3d6446e1308bd98404069276f omxplayer-alsa.patch
e2db0f7ffbe2488dd69ee0bfad006bd863f418554f078ca3432f643de7589d2f omxplayer.initd
530eb9aa50e72fb4828af410b965e0ec7653d1bed87aa86bf04fc340ff3232bd omxplayer.confd"
sha512sums="be14f94876a47b107aea13a23379c0be1df245f064f03b7de7e8cd18fd42a3f5c3a6f2b95a1aa791290c8ea6c202dd9885a76a61d1a56a9a0f6d20dc84e2fa7a omxplayer-0.20160206.tar.gz
......@@ -79,6 +79,6 @@ c349eea5f7c513a07d82a6cf6467c4d21bcb29c053bc5e39d8f675b1212db9beef0abf5248d50ac5
2a8a6def1e09f726cba58c0b9109fa6c4fbd4a3b4f1d27d200488f262a0e0978579d83db7fe24f1d3e03beef318c3674ed79cbd2f1994c4551a59c9fe0f63489 issue-297.patch
3210242f9b834ffec9d3077d5a25caf8be84aa7f4f13c73eb7f61c0a406ec787e4055951fc5a6236f1da7897c95db94a5e11e25d1b3e859a6ea67f31fc6eb517 fix-makefile.patch
8aa58aaa07453186302dc68d92f28c1b50bf0f8fccd50359640a7fc8339b233b32a0c8c02284a9974599e56d69cc557acc25e76e6438c6d64d15afd9c1788a8e default-font.patch
7f12f253321ef25e9645514451b0d57f1d6ec1cada372884d3aa2a1d1529f385490fe0f656f00af7e3bb567c56ba60d4cc310007658841d6e17c92c55ba8184a omxplayer-alsa.patch
911defaed9ca6d0ef1f919517d0cdc0dc6b1c979595cb508958928c892e55c0361cc9929d1fb5bea8ccb3d3556d9028e9c8adf47783a83701f53972a984c1887 omxplayer-alsa.patch
3ddd32235d87a46478d0237ee9b253edeb75729e377b09a33069ecdca2ee230d2851f308897ee75ff69a9f3bdd2876f490bc1667a572dce1c186f80fddcf6df3 omxplayer.initd
4f906ada035869a0e515e7615056b18b0f6906ce4b3a2d34081c0efa79bb9455380f729e7c5270180f5ace89c53a7ac7c93f609e6761825f639f44aa22346bb2 omxplayer.confd"
From 5ff66870da7d3376cba3a927bcb173b87bff9fb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Tue, 9 Feb 2016 15:25:41 +0200
Subject: [PATCH] preliminary alsa support
---
Makefile | 5 +-
OMXAudio.cpp | 5 +-
OMXAudio.h | 1 +
OMXCore.cpp | 11 +
README.md | 1 +
linux/OMXAlsa.cpp | 1275 +++++++++++++++++++++++++++++++++++++++++++++++++++++
linux/OMXAlsa.h | 11 +
omxplayer.cpp | 6 +-
8 files changed, 1310 insertions(+), 5 deletions(-)
create mode 100644 linux/OMXAlsa.cpp
create mode 100644 linux/OMXAlsa.h
diff --git a/Makefile b/Makefile
index 9fc45de..5337ee7 100644
--- a/Makefile
......@@ -122,10 +104,10 @@ index 726127c..cc718b1 100644
-s --stats Pts and buffer stats
diff --git a/linux/OMXAlsa.cpp b/linux/OMXAlsa.cpp
new file mode 100644
index 0000000..b19ef31
index 0000000..fe51eb1
--- /dev/null
+++ b/linux/OMXAlsa.cpp
@@ -0,0 +1,1275 @@
@@ -0,0 +1,1313 @@
+/*
+ * OMX IL Alsa Sink component
+ * Copyright (c) 2016 Timo Teräs
......@@ -136,7 +118,6 @@ index 0000000..b19ef31
+ * any later version.
+ *
+ * TODO:
+ * - rate changing, test --live for speed control handling
+ * - timeouts for state transition failures
+ */
+
......@@ -147,6 +128,7 @@ index 0000000..b19ef31
+#include <stdlib.h>
+#include <pthread.h>
+#include <alsa/asoundlib.h>
+#include <speex/speex_resampler.h>
+#include <IL/OMX_Core.h>
+#include <IL/OMX_Component.h>
+#include <IL/OMX_Broadcom.h>
......@@ -226,11 +208,6 @@ index 0000000..b19ef31
+ q->num++;
+}
+
+static void *gomxq_peek(GOMX_QUEUE *q)
+{
+ return q->head;
+}
+
+static void *gomxq_dequeue(GOMX_QUEUE *q)
+{
+ void *item = q->head;
......@@ -620,7 +597,8 @@ index 0000000..b19ef31
+ void *buf;
+
+ if (port->tunnel_supplier) {
+ CINFO(comp, port, "waiting for supplier buffers");
+ CINFO(comp, port, "waiting for supplier buffers (%d / %d)",
+ (int)port->tunnel_supplierq.num, (int)port->num_buffers);
+ while (port->tunnel_supplierq.num != port->num_buffers)
+ pthread_cond_wait(&port->cond_idle, &comp->mutex);
+
......@@ -634,7 +612,7 @@ index 0000000..b19ef31
+ }
+ } else {
+ /* Wait client / tunnel supplier to allocate buffers */
+ CINFO(comp, port, "waiting buffers to be freed");
+ CINFO(comp, port, "waiting %d buffers to be freed", (int)port->num_buffers);
+ while (port->num_buffers > 0)
+ pthread_cond_wait(&port->cond_no_buffers, &comp->mutex);
+ }
......@@ -809,8 +787,7 @@ index 0000000..b19ef31
+
+ switch (cmd->cmd) {
+ case OMX_CommandFlush:
+ if (port->flush)
+ r = port->flush(comp, port);
+ if (port->flush) r = port->flush(comp, port);
+ break;
+ case OMX_CommandPortEnable:
+ port->def.bEnabled = OMX_TRUE;
......@@ -820,6 +797,7 @@ index 0000000..b19ef31
+ break;
+ case OMX_CommandPortDisable:
+ port->def.bEnabled = OMX_FALSE;
+ if (port->flush) port->flush(comp, port);
+ r = __gomx_port_unpopulate(comp, port);
+ break;
+ default:
......@@ -995,7 +973,8 @@ index 0000000..b19ef31
+ GOMX_QUEUE playq;
+ pthread_cond_t cond_play;
+ size_t frame_size, sample_rate, play_queue_size;
+ int64_t starttime, timescale;
+ int64_t starttime;
+ int32_t timescale;
+ OMX_AUDIO_PARAM_PCMMODETYPE pcm;
+ snd_pcm_format_t pcm_format;
+ char device_name[16];
......@@ -1145,12 +1124,17 @@ index 0000000..b19ef31
+ OMX_HANDLETYPE hComponent = (OMX_HANDLETYPE) comp;
+ OMX_ALSASINK *sink = (OMX_ALSASINK *) hComponent;
+ OMX_BUFFERHEADERTYPE *buf;
+ GOMX_PORT *audio_port = &comp->ports[OMXALSA_PORT_AUDIO];
+ GOMX_PORT *clock_port = &comp->ports[OMXALSA_PORT_CLOCK];
+ snd_pcm_t *dev;
+ snd_pcm_t *dev = 0;
+ snd_pcm_sframes_t n;
+ snd_pcm_hw_params_t *hwp;
+ snd_pcm_uframes_t buffer_size, period_size, period_size_max;
+ SpeexResamplerState *resampler = 0;
+ spx_int16_t *resample_buf = 0;
+ size_t resample_bufsz;
+ unsigned int rate;
+ int32_t timescale;
+ int err;
+
+ CINFO(comp, 0, "worker started");
......@@ -1189,19 +1173,35 @@ index 0000000..b19ef31
+ sink->frame_size = (sink->pcm.nChannels * sink->pcm.nBitPerSample) >> 3;
+ sink->sample_rate = rate;
+
+ resampler = speex_resampler_init(sink->pcm.nChannels, rate, rate, 1, 0);
+ if (!resampler) goto err;
+
+ resample_bufsz = audio_port->def.nBufferSize * 2;
+ resample_buf = (spx_int16_t *) malloc(resample_bufsz);
+ if (!resample_buf) goto err;
+
+ CINFO(comp, 0, "sample_rate %d, frame_size %d", rate, sink->frame_size);
+
+ pthread_mutex_lock(&comp->mutex);
+ while (comp->wanted_state == OMX_StateExecuting) {
+ buf = (OMX_BUFFERHEADERTYPE*) gomxq_peek(&sink->playq);
+ if (!buf || sink->timescale == 0) {
+ buf = 0;
+ if (sink->timescale)
+ buf = (OMX_BUFFERHEADERTYPE*) gomxq_dequeue(&sink->playq);
+ if (!buf) {
+ pthread_cond_wait(&sink->cond_play, &comp->mutex);
+ continue;
+ }
+
+ pthread_mutex_unlock(&comp->mutex);
+ if (buf->nOffset == 0 && clock_port->tunnel_comp &&
+ !(buf->nFlags & OMX_BUFFERFLAG_TIME_UNKNOWN)) {
+ if (resampler && timescale != sink->timescale) {
+ int in_rate = (int64_t)rate * sink->timescale >> 16;
+ timescale = sink->timescale;
+ if (timescale > 0x20000) timescale = 0x20000;
+ CDEBUG(comp, 0, "resampler: %d -> %d", in_rate, rate);
+ speex_resampler_set_rate(resampler, in_rate, rate);
+ }
+
+ sink->play_queue_size -= buf->nFilledLen;
+ if (clock_port->tunnel_comp && !(buf->nFlags & OMX_BUFFERFLAG_TIME_UNKNOWN)) {
+ OMX_TIME_CONFIG_TIMESTAMPTYPE tst;
+ int64_t pts = omx_ticks_to_s64(buf->nTimeStamp);
+ snd_pcm_sframes_t delay = 0;
......@@ -1209,64 +1209,84 @@ index 0000000..b19ef31
+ omx_init(tst);
+ tst.nPortIndex = clock_port->tunnel_port;
+ tst.nTimestamp = buf->nTimeStamp;
+
+ if (resampler && buf->nFlags & OMX_BUFFERFLAG_STARTTIME)
+ speex_resampler_reset_mem(resampler);
+ if (buf->nFlags & (OMX_BUFFERFLAG_STARTTIME|OMX_BUFFERFLAG_DISCONTINUITY)) {
+ OMX_SetConfig(clock_port->tunnel_comp, OMX_IndexConfigTimeClientStartTime, &tst);
+ sink->starttime = pts;
+ CINFO(comp, 0, "STARTTIME nTimeStamp=%llx", pts);
+ sink->starttime = pts;
+ }
+
+ snd_pcm_delay(dev, &delay);
+ if (resampler)
+ delay += speex_resampler_get_input_latency(resampler);
+
+ pts -= (int64_t)delay * OMX_TICKS_PER_SECOND / sink->sample_rate;
+
+ pthread_mutex_unlock(&comp->mutex);
+ if (buf->nFlags & (OMX_BUFFERFLAG_STARTTIME|OMX_BUFFERFLAG_DISCONTINUITY))
+ OMX_SetConfig(clock_port->tunnel_comp, OMX_IndexConfigTimeClientStartTime, &tst);
+ if (pts >= sink->starttime) {
+ tst.nTimestamp = omx_ticks_from_s64(pts);
+ OMX_SetConfig(clock_port->tunnel_comp, OMX_IndexConfigTimeCurrentAudioReference, &tst);
+ }
+ pthread_mutex_lock(&comp->mutex);
+ }
+
+ n = 0;
+ if (buf->nFlags & (OMX_BUFFERFLAG_DECODEONLY|OMX_BUFFERFLAG_CODECCONFIG|OMX_BUFFERFLAG_DATACORRUPT)) {
+ CDEBUG(comp, 0, "skipping: %d bytes, flags %x", buf->nFilledLen, buf->nFlags);
+ n = buf->nFilledLen;
+ } else if (buf->nFilledLen) {
+ n = snd_pcm_writei(dev, buf->pBuffer + buf->nOffset, buf->nFilledLen / sink->frame_size);
+ if (n < 0) {
+ if (n != -EPIPE) {
+ CINFO(comp, 0, "alsa error: %ld", n);
+ pthread_mutex_lock(&comp->mutex);
+ break;
+ } else {
+ spx_int16_t *in_ptr;
+ uint8_t *out_ptr;
+ spx_uint32_t in_len, out_len;
+ pthread_mutex_unlock(&comp->mutex);
+
+ in_ptr = (spx_int16_t *)(buf->pBuffer + buf->nOffset);
+ in_len = buf->nFilledLen / sink->frame_size;
+
+ if (resampler) {
+ out_len = resample_bufsz / sink->frame_size;
+ speex_resampler_process_interleaved_int(
+ resampler,
+ in_ptr, &in_len,
+ resample_buf, &out_len);
+ out_ptr = (uint8_t *) resample_buf;
+ } else {
+ out_ptr = (uint8_t *) in_ptr;
+ out_len = in_len;
+ }
+
+ while (out_len > 0) {
+ n = snd_pcm_writei(dev, out_ptr, out_len);
+ if (n < 0) {
+ CINFO(comp, 0, "alsa error: %ld: %s", n, snd_strerror(n));
+ snd_pcm_prepare(dev);
+ n = 0;
+ }
+ CINFO(comp, 0, "underrun");
+ snd_pcm_prepare(dev);
+ n = 0;
+ out_len -= n;
+ n *= sink->frame_size;
+ out_ptr += n;
+ }
+ n *= sink->frame_size;
+ pthread_mutex_lock(&comp->mutex);
+ }
+ pthread_mutex_lock(&comp->mutex);
+
+ buf->nOffset += n;
+ buf->nFilledLen -= n;
+ sink->play_queue_size -= n;
+
+ if (!buf->nFilledLen) {
+ __gomx_process_mark(comp, buf);
+ if (buf->nFlags & OMX_BUFFERFLAG_EOS) {
+ CDEBUG(comp, 0, "end-of-stream");
+ __gomx_event(comp, OMX_EventBufferFlag, OMXALSA_PORT_AUDIO, buf->nFlags, 0);
+ }
+ if (gomxq_peek(&sink->playq) == (void*) buf) {
+ buf = (OMX_BUFFERHEADERTYPE*) gomxq_dequeue(&sink->playq);
+ __gomx_empty_buffer_done(comp, buf);
+ }
+ __gomx_process_mark(comp, buf);
+ if (buf->nFlags & OMX_BUFFERFLAG_EOS) {
+ CDEBUG(comp, 0, "end-of-stream");
+ __gomx_event(comp, OMX_EventBufferFlag, OMXALSA_PORT_AUDIO, buf->nFlags, 0);
+ }
+ __gomx_empty_buffer_done(comp, buf);
+ }
+ pthread_mutex_unlock(&comp->mutex);
+cleanup:
+ if (dev) snd_pcm_close(dev);
+ if (resampler) speex_resampler_destroy(resampler);
+ free(resample_buf);
+ CINFO(comp, 0, "worker stopped");
+ return 0;
+
+alsa_error:
+ CINFO(comp, 0, "ALSA error: %s", snd_strerror(err));
+err:
+ pthread_mutex_lock(&comp->mutex);
+ /* FIXME: Current we just go to invalid state, but we might go
+ * back to Idle with ErrorResourcesPreempted and let the client
......@@ -1280,8 +1300,8 @@ index 0000000..b19ef31
+static OMX_ERRORTYPE omxalsasink_audio_do_buffer(GOMX_COMPONENT *comp, GOMX_PORT *port, OMX_BUFFERHEADERTYPE *buf)
+{
+ OMX_ALSASINK *sink = (OMX_ALSASINK *) comp;
+ gomxq_enqueue(&sink->playq, (void *) buf);
+ sink->play_queue_size += buf->nFilledLen;
+ gomxq_enqueue(&sink->playq, (void *) buf);
+ pthread_cond_signal(&sink->cond_play);
+ return OMX_ErrorNone;
+}
......@@ -1291,8 +1311,8 @@ index 0000000..b19ef31
+ OMX_ALSASINK *sink = (OMX_ALSASINK *) comp;
+ OMX_BUFFERHEADERTYPE *buf;
+ while ((buf = (OMX_BUFFERHEADERTYPE *) gomxq_dequeue(&sink->playq)) != 0) {
+ __gomx_empty_buffer_done(comp, buf);
+ sink->play_queue_size -= buf->nFilledLen;
+ __gomx_empty_buffer_done(comp, buf);
+ }
+ return OMX_ErrorNone;
+}
......@@ -1449,6 +1469,3 @@ index 3b5e6d2..4032ba3 100644
case 'i':
m_dump_format = true;
m_dump_format_exit = true;
--
2.7.1
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment