[Icecast] patch for native iphone support

Greg Ogonowski
Mon, 25 Aug 2008 03:04:49 -0000

iPhone DOES NOT natively support HE-AAC/aacPlus.

If you are able to take advantage of the embedded AAC decoder with a
custom app or a progressive download as this patch provides, you will
decode HE-AAC/aacPlus as core AAC only. What this means specifically
is that a 15kHz Parameteric Stereo HE-AAC/aacPlus stream will decode
on iPhone as about 8Khz AAC Mono only. The only way to get Hi-Fi
Stereo on iPhone is to encode as 96-128kbps AAC Stereo. This is
obviously a reliability problem in the making for the 3G networks.

We are working on a custom iPhone app to support genuine Dolby/Coding
Technologies HE-AAC and solve this problem. Anyone interested in
this, please contact me off this list, as this is off topic for the
Icecast list. We are eternally grateful for the Icecast group support
in allowing multiple content types to specify AAC/HE-AAC streaming. I
would like to return that respect by taking this business off this
list, unless it is truly welcome.

-greg.
ORBAN.



At 18:48 2008-08-24, oddsock wrote:
>Here is a patch for icecast 2.3.2 that adds support for listening to
>mp3 and aac+ streams on the iphone.
>
>A quick background on the technical aspects of the patch and why it
>is needed :
>
>With the advent of 3g on the iphone, lots of people have been
>jumping on the bandwagon of providing internet radio streams that
>work on the iPhone.  The biggest problem is that (without having to
>install an dedicated app) in order to listen to streams on an iphone
>you need to use the embedded quicktime player.  Now quicktime
>supports both mp3 and aac+, however it only supports the streaming
>of them insomuch as if you are doing on-demand streaming (i.e. from
>an apache server).  I don't know WHY they don't support standard
>HTTP-based mp3 or aac+ streams from Icecast or Shoutcast, but they
>don't... At least not reliably.
>
>So, when a quicktime embedded object is configured with an icecast
>stream on the iphone, the first thing the quicktime object does is
>to check to see if the stream supports the "Range" semantics.
Files
>served from a webserver will support this, however icecast (and I'm
>pretty sure Shoutcast as well) do not.  The quicktime object expects
>RTSP (I believe) and not HTTP for live internet streams.  Anyway, so
>in order to "fake out" the quicktime object, I've added basic
>support for the "Range" http request header.  This does NOT mean
>that seeking within a stream will be supported, it's just a hack
>honestly (and why it's not probably going to be committed) just to
>get the embedded quicktime player to work.
>
>So, essentially, the quicktime player will connect and ask for bytes
>1-2 of the stream (just a test to see if it's seekable), and as long
>as it gets the proper response code (HTTP 206 Partial Content), it
>will happily start streaming on a second connection.
>
>Anyway, here is the patch, it's pretty simple, and should work with
>aac+ although I've not tested it with that.  It will NOT work with
>ogg vorbis, but then again, ogg vorbis isn't supported on the
>quicktime embedable object on the iPhone.
>
>Enjoy!
>
>Begin Patch
>--------------------
>Index: src/format_mp3.c
>==================================================================>---
src/format_mp3.c    (revision 15198)
>+++ src/format_mp3.c    (working copy)
>@@ -639,6 +639,9 @@
>      char *ptr = client->refbuf->data + client->refbuf->len -
2;
>      int bytes;
>      const char *useragent;
>+    char *range;
>+    int rangenumber;
>+    int rangenumber2;
>
>      if (client_mp3 == NULL)
>          return -1;
>@@ -657,7 +660,44 @@
>          remaining -= bytes;
>          ptr += bytes;
>      }
>+    range = httpp_getvar (client->parser, "range");
>
>+    if (range != NULL) {
>+        int ret = 0;
>+        int rangeproblem = 0;
>+        ret = sscanf(range, "bytes=%d-%d", &rangenumber,
&rangenumber2);
>+        if (ret != 2) {
>+            rangeproblem = 1;
>+        }
>+        if (rangenumber < 0) {
>+            rangeproblem = 1;
>+        }
>+        if (!rangeproblem) {
>+            char currenttime[50];
>+            time_t now;
>+            int strflen;
>+            struct tm result;
>+            time(&now);
>+            strflen = strftime(currenttime, 50, "%a, %d-%b-%Y %X
GMT",
>+                               gmtime_r(&now, &result));
>+            client->respcode = 206;
>+
>+            bytes = snprintf (ptr, remaining, "Date: %s\r\n",
currenttime);
>+            if (bytes > 0)
>+            {
>+                remaining -= bytes;
>+                ptr += bytes;
>+            }
>+            bytes = snprintf (ptr, remaining, "Content-Range: bytes
>%d-%d/221183499\r\n",
>+                                               rangenumber, rangenumber2);
>+            if (bytes > 0)
>+            {
>+                remaining -= bytes;
>+                ptr += bytes;
>+            }
>+        }
>+    }
>+
>      client->format_data = client_mp3;
>      client->free_client_data = free_mp3_client_data;
>      metadata = httpp_getvar(client->parser, "icy-metadata");
>Index: src/format.c
>==================================================================>---
src/format.c    (revision 15198)
>+++ src/format.c    (working copy)
>@@ -279,13 +279,22 @@
>      int bitrate_filtered = 0;
>      avl_node *node;
>      ice_config_t *config;
>+    char *range;
>
>      remaining = client->refbuf->len;
>      ptr = client->refbuf->data;
>      client->respcode = 200;
>
>-    bytes = snprintf (ptr, remaining, "HTTP/1.0 200 OK\r\n"
>+    range = httpp_getvar (client->parser, "range");
>+
>+    if (range) {
>+        bytes = snprintf (ptr, remaining, "HTTP/1.1 206 Partial
Content\r\n"
>+                "Content-Type: %s\r\n",
source->format->contenttype);
>+    }
>+    else {
>+        bytes = snprintf (ptr, remaining, "HTTP/1.0 200 OK\r\n"
>              "Content-Type: %s\r\n",
source->format->contenttype);
>+    }
>
>      remaining -= bytes;
>      ptr += bytes;
>-----------------------
>End Patch
>Ed
>_______________________________________________
>Icecast mailing list
>Icecast at xiph.org
>http://lists.xiph.org/mailman/listinfo/icecast


__________________________________________________________________________
Greg J. Ogonowski
VP Product Development
ORBAN / CRL, Inc.
Diamond Bar, CA  91765  USA
greg at orban.com