1

APIでストリーミングしているIPカメラからオーディオを再生しようとしていますhttp://...<ip-camera..>/audio.cgi

現在、MJPEGクライアントを適応させてストリームオーディオを再生し、オーディオブロックを取得して、NSMutableArray連続するサウンドパッケージのバッファ()に配置しています。ここにデータを受け取るいくつかのコードがあります:

-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSLog(@"Data recv.");

     NSLog(@"Data lenght:%i",[data length]);

    if ([data length]>AUDIO_STREAM_HEADER_SIZE){
        [recvData appendData:data]; //audio stream data - always 1024 bytes
        NSLog(@"Data Append lenght:%i",[recvData length]);

    }
    else {
        [_encabezado appendData:data]; //audio stream header - always 44 bytes
        NSLog(@"Crea encabezado:%@",_encabezado);
        NSLog(@"Largo encabezado:%i",[_encabezado length]);

    }


    if ([recvData length] >= PACKET_SIZE_BUFFER_SONIDO) //PACKET_SIZE_BUFFER_SONIDO = 81920
    {

        NSMutableData *soundData = [[NSMutableData alloc] initWithCapacity:([recvData length])];

        NSMutableData *soundCut = [[NSMutableData alloc] initWithData:recvData];

        [soundData appendData:_encabezado]; //audio stream header
        [soundData appendData:soundCut];  //audio stream data

        [_arrSonidos addObject:soundData];

        if ([_arrSonidos count]>(BUFFER_SIZE_FOR_PLAY-1)) {
            if (playerBuffer.isPlaying) {
                [playerBuffer AgregaDataSound:soundData]; //addDataSound in Buffer
            } else {
                playerBuffer = [[SoundDataPLayer alloc]initWithFileNameQueue:_arrSonidos];
            }
        }

        [recvData setLength:0];

        [soundData release];
    }

}

関数が呼び出される(関数が表示される)たびに、データフィールドのヘッダーは(44バイト)を取得し、その後、呼び出しごとに1回データバイト(1024バイト)のビットを取得します。私がしていることは、ヘッドがデータをNSData受信し、定義されたパケットサイズまでデータを受信し、パッケージをそれぞれのヘッダーデータとともにバッファーに保持することです。そのため、バッファにパッケージを追加することを繰り返しました。

一方、私は上記のコードによって呼び出される「playerBuffer」(Web上の例に触発された)を作成し、バッファーの制御とバッファーのすべてのパケットの再生も担当します。このオブジェクトは:に基づいていAVAudioPlayerます

SoundDataPLayer.h

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

@interface SoundDataPLayer : NSObject <AVAudioPlayerDelegate> {
    AVAudioPlayer* myplayer;
    NSMutableArray* dataSound;
    int index;
}

@property (nonatomic, retain) AVAudioPlayer* myplayer;
@property (nonatomic, retain) NSMutableArray* dataSound;

- (id)initWithFileNameQueue:(NSArray*)datas;
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
- (void)playX:(int)i;
- (void)stop;
- (BOOL)isPlaying;
- (void)AgregaDataSound:(NSData *)data;

@end

SoundDataPLayer.m

#import "SoundDataPLayer.h"
#import "ExtAudioFileConvertUtil.h"

@implementation SoundDataPLayer

@synthesize myplayer;
@synthesize dataSound;

- (id)initWithFileNameQueue:(NSArray*)datas {
    if ((self = [super init])) {
        self.dataSound = [[NSMutableArray alloc]initWithArray:datas];
        index = 0;
        [self playX:index];
    }
    return self;
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    if (index < dataSound.count) {
        [self playX:index];
    } else {
        //reached end of queue
    }
}

- (void)playX:(int)i {

    self.myplayer = [[AVAudioPlayer alloc] initWithData:[dataSound objectAtIndex:i]  error:nil];
    myplayer.delegate = self;
    [myplayer prepareToPlay];
    [myplayer play];

    index++;
}

- (void)stop {
    if (self.myplayer.playing) [myplayer stop];
}

- (BOOL)isPlaying{
    return self.myplayer.playing;
}

- (void)AgregaDataSound:(NSData *)data {
    [dataSound addObject:data]; //Add Sound Data to the buffer
}

@end

これは、オーディオをループ再生する作業ですが、ループごとに、バッファAVAudioPlayerの新しいパケット()を再生するために戻るとNSData、各パケット間に迷惑なグリッチが聞こえます。

グリッチを含むデータがあるかどうかを確認するために、サウンドパックバッファをデータファイルに記録してみましSystemSoundたが、明らかにグリッチがデータの最後にあるという事実があります。

フォーラムで何が起こっているのかを説明しているように見える記事を見つけました。ここでは、x-wavオーディオとPCMコーデックであるため、私の場合は完全には説明されていないようです。NSDataパケットからオーディオを解凍する方法はわかりませんが。

IPカメラからのストリーミングオーディオの追加情報:

datos del audio en elヘッダー:

"Cache-Control"="キャッシュなし"; "Content-Type" = "audio / x-wav"; 日付="2010年1月5日火曜日01:17:04"; プラグマ="キャッシュなし"; サーバー="GoAhead-Webs";

Datos adicionales del audioコーデック:PCMサンプルレート:16 kHz

誰かがこの問題を解決する方法を教えてくれたら幸いです...私は何時間もそれを解決しようとしています...私を夢中にさせています!!

事前に感謝し、私の悪い英語をお詫びします。

4

2 に答える 2

1

聞こえる「グリッチ」は、「再生が終了しました」イベントを受信して​​処理し、次のデータパケット用にAVAudioPlayerを初期化して、データをサウンドカードに送信するのにかかる時間の組み合わせです。

あるCDプレーヤーの再生が終了するのを待ってから次のプレーヤーを開始するのと似ています。グリッチのない再生を行うのに十分な速さで反応することは不可能です。

おそらくオーディオキューサービスを使用したいと思うでしょうし、カメラと電話の間のオーディオクロックスキューを補正する方法も必要になるでしょう。

于 2013-03-28T04:33:15.683 に答える
1

AVQueuePlayerの問題を解決します。

私はそれが誰かを助けることを願っています。

于 2013-05-06T01:29:00.650 に答える