2012-12-12 2 views
0

내 앱에서는 기기의 기본 마이크에서 사운드를 녹음하고 스트리밍을 위해 RTSP 서버로 보내야합니다.iOS : RTSP 서버에 메모리 오디오 데이터 업로드

내 레코더 주 구조는 다음과 같습니다

typedef struct AQRecorderState { 
    AudioStreamBasicDescription mDataFormat;     // 2 
    AudioQueueRef    mQueue;      // 3 
    AudioQueueBufferRef   mBuffers[kNumberRecordBuffers];// 4 
    AudioFileID     mAudioFile;     // 5 
    UInt32      bufferByteSize;    // 6 
    SInt64      mCurrentPacket;    // 7 
    bool       mIsRunning;     // 8 
}AQRecorderState; 

녹화에 대한 나의 설정 매개 변수는 다음과 같습니다

ars.mDataFormat.mSampleRate  = 44100; 
    ars.mDataFormat.mChannelsPerFrame = 1; 
    ars.mDataFormat.mFramesPerPacket = 1; 
    ars.mDataFormat.mBitsPerChannel  = 16; 
    ars.mDataFormat.mBytesPerFrame  = ars.mDataFormat.mChannelsPerFrame * sizeof (SInt16); // BYTES_PER_FRAME; 
    ars.mDataFormat.mBytesPerPacket  = ars.mDataFormat.mChannelsPerFrame * sizeof (SInt16); // BYTES_PER_PACKET; 

    /*----------------- FORMAT -------------------*/ 
    ars.mDataFormat.mFormatID = kAudioFormatLinearPCM; 
    ars.mDataFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; 

    // derive the buffer size 
    DeriveBufferSize(ars.mQueue, ars.mDataFormat, kBufferSeconds, &ars.bufferByteSize); 

    // create the queue 
    AudioQueueNewInput(&ars.mDataFormat, 
         AQInputCallback, 
         (__bridge void *)(self), 
         NULL, 
         kCFRunLoopCommonModes, 
         0, 
         &ars.mQueue); 

// set the magic cookie for the queue 
    setMagicCookieForFile(ars.mQueue, ars.mAudioFile); 

    // allocate and enque the recording buffers 
    for (int i=0; i<kNumberRecordBuffers; i++){ 
     AudioQueueAllocateBuffer(ars.mQueue, ars.bufferByteSize, &ars.mBuffers[i]); 
     AudioQueueEnqueueBuffer(ars.mQueue, ars.mBuffers[i], 0, NULL); 
    } 

    // set current packet index and run state 
    ars.mCurrentPacket = 0; 
    ars.mIsRunning = true; 

    // start the recording 
    AudioQueueStart(ars.mQueue, NULL); 

그리고 내 입력 콜백이 보이는처럼 :

static void AQInputCallback(void *aqRecorderState, 
      AudioQueueRef      inQ, 
      AudioQueueBufferRef     inBuffer, 
      const AudioTimeStamp     *timestamp, 
      unsigned long      inNumPackets, 
      const AudioStreamPacketDescription *mDataFormat) 
{ 

    NSLog(@"........Callback called"); 
    AppDelegate *THIS=(__bridge AppDelegate *)aqRecorderState; 
    AQRecorderState *pArs = &(THIS->ars); 

    if (inNumPackets > 0) { 
     write_audio_frame(THIS->oc, THIS->audio_st); 
     // Stream audio frame 
     uint8_t *data; 

     AVCodecContext *codec; 
     AVPacket packet; 
     uint32_t size = inBuffer->mAudioDataByteSize; 

     long sample_time_ms = (long)(timestamp->mSampleTime * 1000/SAMPLE_RATE); 

     codec = THIS->audio_st->codec; 

     data = av_malloc(size*100); 
     if (!data) { 
      fprintf(stderr, "Couldn't allocate data for audio_frame\n"); 
      exit(1); 
     } 

     NSLog(@"Size 1 : %d",size); 

     av_init_packet(&packet); 
     packet.size = avcodec_encode_audio(codec, data, size, inBuffer->mAudioData); 

     NSLog(@"Size 2: %d",packet.size); 

     packet.data = data; 
     packet.pts = sample_time_ms; 
     packet.dts = sample_time_ms; 
     packet.flags |= AV_PKT_FLAG_KEY; 
     packet.duration = (size * 8 * 1024 * 1000000)/BITS_PER_CHANNEL; 
     packet.stream_index = THIS->audio_st->index; //audio_st->index 

     pArs->mCurrentPacket += inNumPackets; // advance packet index pointer 

     if (av_interleaved_write_frame(THIS->oc, &packet) != 0) { 
      exit(1); 
     } 

     pArs->mCurrentPacket += inNumPackets; // advance packet index pointer 

     av_free(data); 
    } 

} 

입력 콜백에서 데이터를 가져 오는 중입니다. 파일에 기록한 다음 재생하면 문제가 없지만 파일에 저장하지 않고 직접 RTSP 서버로 보내는 것이 좋습니다.

참고 : 내가 서버에 프레임을 작성하기위한 av_interleaved_write_frame()를 사용하고, 나는 내가 서버 측에서 패킷 "순서가"무엇입니까 왜 문제가 내 입력 콜백과 먹으 렴에 AVPacket 변환에 생각합니다.

인터넷을 통해 어디에서나 검색했지만 아무 것도 찾을 수 없습니다. 누군가 그것에 대해 어떤 생각이 있으면 도움을주십시오.

답변

0

당신은 tcp 또는 udp를 사용하고 있습니까, 나는 순서가 잘못된 패킷을 생각하고 udp는 패킷을 떨어 뜨리면 ffmpeg가 필요한 경우 패킷을 다시 정렬 할 수 있습니다.

+0

rtmp를 사용하고 있습니다. – Yuvrajsinh

관련 문제