내 앱에서는 기기의 기본 마이크에서 사운드를 녹음하고 스트리밍을 위해 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
변환에 생각합니다.
인터넷을 통해 어디에서나 검색했지만 아무 것도 찾을 수 없습니다. 누군가 그것에 대해 어떤 생각이 있으면 도움을주십시오.
rtmp를 사용하고 있습니다. – Yuvrajsinh