3

I have been trying to create a source client for ice cast for ios. I have been able to connect using asyncsocket to connect to the socket. I am also able to write data to the server. The icecast configuration is done for mp3 format. But the mp3 file written to the server is corrupt. I am providing some code snippets.

Header:

 NSString *string = @"SOURCE /sync HTTP/1.0\r\n"
        "Authorization: Basic c291cmNlOmhhY2ttZQ==\r\n"
        "User-Agent: butt-0.1.12\r\n"
        "User-Agent: butt-0.1.12\r\n"
        "content-type: audio/mpeg\r\n"
        "ice-name:  sync's Stream\r\n"
        "ice-public: 0\r\n"
        "ice-genre: Rock\r\n"
        "ice-description: This is my server description\r\n"
        "Connection: keep-alive\r\n"
        "ice-audio-info: ice-samplerate=44100;ice-bitrate=48;ice-channels=2\r\n\r\n";

     NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

    //sending http request to write the header
    NSLog(@"Sending HTTP Request.");
    [socket writeData:data withTimeout:-1 tag:1];

    //write buffer data to server
    [socket writeData:self.dataBuffer withTimeout:-1 tag:1];

for recording i am using aqrecorder using the following code to record it.

void AQRecorder::MyInputBufferHandler(  void *                              inUserData,
                                        AudioQueueRef                       inAQ,
                                        AudioQueueBufferRef                 inBuffer,
                                        const AudioTimeStamp *              inStartTime,
                                        UInt32                              inNumPackets,
                                        const AudioStreamPacketDescription* inPacketDesc)
{
    AQRecorder *aqr = (AQRecorder *)inUserData;
    try {
        if (inNumPackets > 0) {
            // write packets to file
            XThrowIfError(AudioFileWritePackets(aqr->mRecordFile, FALSE, inBuffer->mAudioDataByteSize,
                                             inPacketDesc, aqr->mRecordPacket, &inNumPackets, inBuffer->mAudioData),
                       "AudioFileWritePackets failed");
            aqr->mRecordPacket += inNumPackets;

           NSLog(@"size = %u",(unsigned int)inBuffer->mAudioDataByteSize);

            data = [[[NSData alloc]initWithBytes:inBuffer->mAudioData length:inBuffer->mAudioDataByteSize]retain];

            server *srv = [[server alloc]init];
            srv.dataBuffer=data;
            [srv connecting];

        }

        // if we're not stopping, re-enqueue the buffe so that it gets filled again
        if (aqr->IsRunning())
            XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL), "AudioQueueEnqueueBuffer failed");
    } catch (CAXException e) {
        char buf[256];
        fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
    }
}



void AQRecorder::StartRecord(CFStringRef inRecordFile)
{
//    server *srv=[[server alloc]init];
//    [srv connecting];

    int i, bufferByteSize;
    UInt32 size;
    CFURLRef url = nil;

    try {       
        mFileName = CFStringCreateCopy(kCFAllocatorDefault, inRecordFile);

//      // specify the recording format
//      SetupAudioFormat(kAudioFormatMPEG4AAC);

        // specify the recording format, use hardware AAC if available
        // otherwise use IMA4
        if(IsAACHardwareEncoderAvailable())
            SetupAudioFormat(kAudioFormatMPEG4AAC);
        else
            SetupAudioFormat(kAudioFormatAppleIMA4);

        // create the queue
        XThrowIfError(AudioQueueNewInput(
                                      &mRecordFormat,
                                      MyInputBufferHandler,
                                      this /* userData */,
                                      NULL /* run loop */, NULL /* run loop mode */,
                                      0 /* flags */, &mQueue), "AudioQueueNewInput failed");

        // get the record format back from the queue's audio converter --
        // the file may require a more specific stream description than was necessary to create the encoder.
        mRecordPacket = 0;

        size = sizeof(mRecordFormat);
        XThrowIfError(AudioQueueGetProperty(mQueue, kAudioQueueProperty_StreamDescription,  
                                         &mRecordFormat, &size), "couldn't get queue's format");

        NSString *recordFile = [NSTemporaryDirectory() stringByAppendingPathComponent: (NSString*)inRecordFile];    

        //url = CFURLCreateWithString(kCFAllocatorDefault, (CFStringRef)recordFile, NULL);
        url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)recordFile, kCFURLPOSIXPathStyle, false);
        // create the audio file
        OSStatus status = AudioFileCreateWithURL(url, kAudioFileCAFType, &mRecordFormat, kAudioFileFlags_EraseFile, &mRecordFile);
        CFRelease(url);

        XThrowIfError(status, "AudioFileCreateWithURL failed");

        // copy the cookie first to give the file object as much info as we can about the data going in
        // not necessary for pcm, but required for some compressed audio
        CopyEncoderCookieToFile();

        // allocate and enqueue buffers
        bufferByteSize = ComputeRecordBufferSize(&mRecordFormat, kBufferDurationSeconds);   // enough bytes for half a second
        for (i = 0; i < kNumberRecordBuffers; ++i) {
            XThrowIfError(AudioQueueAllocateBuffer(mQueue, bufferByteSize, &mBuffers[i]),
                       "AudioQueueAllocateBuffer failed");
            XThrowIfError(AudioQueueEnqueueBuffer(mQueue, mBuffers[i], 0, NULL),
                       "AudioQueueEnqueueBuffer failed");
        }
        // start the queue
        mIsRunning = true;
        XThrowIfError(AudioQueueStart(mQueue, NULL), "AudioQueueStart failed");
    }
    catch (CAXException e) {
        char buf[256];
        fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
    }
    catch (...) {
        fprintf(stderr, "An unknown error occurred\n");;
    }   

}

Do i need to change the format to write to the server?

Naresh
  • 433
  • 2
  • 15

1 Answers1

1

You're not sending MP3 data, you're sending AAC or M4A data. I don't believe Icecast supports M4A. Are you actually using Icecast or some other server?

For AAC, your Content-Type header is wrong. Try audio/aac, audio/aacp, audio/mp4 or audio/mpeg4-generic.

Also, you only need one User-Agent header, and you should pick something that matches the software you are writing rather than copying someone else's. In the future, there might need to be an adjustment of protocol for your code, and that would only be possible if you used your own user-agent string.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • I am using icecast server and if i use kAudioFormatLinearPCM what should be the Content-Type – Naresh Jul 22 '13 at 05:47
  • @NareshKukkala, You could try `audio/wav`, but I'm not sure that Icecast supports this. It's not just about the stream, there is a container (file header in your case) that needs to be sent before the stream data to tell the client how to decode it. This is especially important for PCM, as those are just raw samples. There are no internal frame headers in PCM audio, so the initial header needs to tell the player what the sample rate, bit depth, and endianess of the data. – Brad Jul 22 '13 at 12:58
  • my icecast is configure to mp3 format. When i open the server written file it does not contain the header details. what can be the solution for setting header to audio file – Naresh Jul 23 '13 at 06:00
  • i am able to send data to server stream by stream but only noise is played – Naresh Jul 24 '13 at 10:25
  • If your server is configured to use MP3, then you must send MP3 data. – Brad Jul 24 '13 at 13:49
  • but ios does not support mp3 encoding what options do i have in this case? – Naresh Jul 24 '13 at 13:53
  • @NareshKukkala, Then you need to pick a codec that is supported. You could use FLAC and transcode server-side, but that takes quite a bit of bandwidth. – Brad Jul 24 '13 at 13:54
  • does apple support FLAC? How do i transcode server side? any links that could be helpful ? Do you know anyother supported formats by icecast and ios? – Naresh Jul 24 '13 at 13:58
  • @NareshKukkala, I'm not an iOS developer and cannot tell you what codecs would be supported. You can uses Ices to transcode your streams server-side. Check out http://www.stmental.net/~dfoster/icesmanual.html – Brad Jul 24 '13 at 14:34
  • only one packet is been written how to write as many packet generated to server – Naresh Jul 27 '13 at 10:02