Ice cast source client for ios

2020-02-29 14:20发布

问题:

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?

回答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.