2012-10-16 109 views
1

我想使用iPhone作爲ICEcast流的音頻源。Icecast流源客戶端iOS

1)是AudioQueueInputCallback,我應該發送這個流?

2)我已經能夠識別出協議的Icecast Icecast 2: protocol description, streaming to it using C# 但是,我不能肯定如何在回調代碼做到這一點(即如何發送二進制音頻)

UPDATE

static void MyAQInputCallback(void *inUserData, 
    AudioQueueRef inQueue, 
    AudioQueueBufferRef inBuffer, 
    const AudioTimeStamp *inStartTime, 
    UInt32 inNumPackets, 
    cont AudioStreamPacketDescription *inPacketDesc) 
{ 

    if (inNumPackets > 0) 
    { 
     // instead of 
     //  AudioFileWritePackets(someFile, FALSE, 
     //   inBuffer->mAudioDataByteSize, 
     //   inPacketDesc, recordPacketNumber, 
     //   &inNumPackets, inBuffer->mAudioData); 

     // I want to send to http://myicecastserver 
     // instead 
    } 

} 

UPDATE

我會打開一個套接字連接到我的Icecast服務器發送數據。

+0

你可以發佈你到目前爲止的代碼嗎? – Brad

+0

我添加了一些代碼。 – JonathanC

+0

@JonathanC嗨,你做到了嗎?你能分享一下代碼嗎?你如何將數據發送到icecast服務器?你正在使用哪個套接字庫? – TheTiger

回答

1

這是一個不平凡的問題。你提到的「協議」只是一些人嗅探幾包並做出一些猜測。如果您檢查ICES源代碼,您可以看到發送到Icecast服務器的實際方法,它是一個非常複雜的自定義流協議。假設您的流已經編碼爲PCM,相關的代碼位於兩個文件中:stream.c和stream_shared.c。爲了讓在此流算法的複雜感,這裏是從發件人小摘錄:

else if (sdsc->enc) 
    { 
     ogg_page og; 
     int be = (sdsc->input->subtype == INPUT_PCM_BE_16)?1:0; 
     int ret=1; 

     /* We use critical as a flag to say 'start a new stream' */ 
     if(buffer->critical) 
     { 
      if(sdsc->resamp) { 
       resample_finish(sdsc->resamp); 
       encode_data_float(sdsc->enc, sdsc->resamp->buffers, 
         sdsc->resamp->buffill); 
       resample_clear(sdsc->resamp); 
       sdsc->resamp = resample_initialise (sdsc->stream->channels, 
         sdsc->stream->resampleinrate, sdsc->stream->resampleoutrate); 
      } 
      encode_finish(sdsc->enc); 
      while(encode_flush(sdsc->enc, &og) != 0) 
      { 
       if ((ret = stream_send_data(sdsc, og.header, og.header_len)) == 0) 
        return 0; 
       if ((ret = stream_send_data(sdsc, og.body, og.body_len)) == 0) 
        return 0; 
      } 
      encode_clear(sdsc->enc); 

      if(sdsc->input->metadata_update) 
      { 
       vorbis_comment_clear(&sdsc->vc); 
       vorbis_comment_init(&sdsc->vc); 

       sdsc->input->metadata_update(sdsc->input->internal, &sdsc->vc); 
      } 

正如我所說的,這是代碼的只有10%左右。如果你想創建一個定製的Icecast源客戶端,你將不得不復制所有這些代碼,將它移植到你的程序中,然後將你的輸入編碼爲PCM,然後打包它用於傳遞到stream.c和stream_shared.c中的例程。

+0

我想這是做到這一點的正確方法。我正在研究一個概念證明,所以我認爲我的第一步就是嘗試使用其他人通過嗅探數據包收集的信息創建一個基本的源客戶端。然後,我可能會嘗試做一個適當的端口。 – JonathanC

+1

@泰勒,如果您對我的回答有更正,請做。當然,如果你想在你的項目中包含GPL代碼,你可以使用Icecast源客戶端的代碼。如果你有時間在你的手上,你可以把它分開,並通過它。或者,您可以查看正在發送的原始數據,這非常簡單。我並不反對在可能的情況下使用已經建立的方法是可行的方式,但是你暗示我發佈的內容是不正確的,因爲它是基於觀察寫的。我不同意。再次,如果您發現有問題,請隨時編輯或發表評論,我會編輯。 – Brad