目前已实做到藉由ffmpeg接收RTSP流媒体并播放(3gp格式 AAC编码)。问题在于解码后播出的声音充满杂音,有些段落甚至被扭曲。但在先前用本地端AAC档案测试时,杂讯的程度并不是太严重。因为是第一次作流媒体客户端,说实在看不出整体设置的确切问题在哪边,还请有相关经验的前辈们帮忙看看,感谢!约略流程
-- 开启流媒体,取得格式,开启读帧与解码线程
   -- 读取音频流frame
   -- 解码,得到raw audio
   -- 写入暂存queue ( AVPacket  audio_buffer[ABUF_SIZE]; // ABUF_SIZE)
-- 播放开始:开启AudioQueue,设置音频格式,AudioBuffer
   -- 从暂存queue抓取raw audio写入AudioBuffer-- 读帧与解码 -- void *parseThread(void *data){
    long                    len;
    struct ring *           r;
    int                     limit;
    video_data_t *          v = (video_data_t*)data;
    struct video_context_t *c = v->context;
    AVPacket*               pkt;
        
    printf("\n\rvideo_inst.c::parseThread: Parse Thread Started.\n");
    int16_t  *pDecodeBuf=(int16_t*) av_malloc(DECODEBUF_SIZE);
    
    int decodedsize = DECODEBUF_SIZE;
    UInt16 inNumofBytes = 0;
    OSStatus audioErr;    // Parse loop
    while(likely(!(c->play_state & STATE_DIE)))
    {
        
        if(unlikely(c->seek_req > 0)){
            // Received a request to seek
            drainBuffers(v);  // 重设buffer
            av_seek_frame(c->p_format_ctx, -1, c->seek_req * AV_TIME_BASE, 0); // Seek to the appropriate time
            
            c->seek_req = 0;
            c->play_state ^= (c->play_state & STATE_EOF);  // If we've reached EOF, we aren't there any longer.
            continue;
        }
        if(unlikely((c->play_state & STATE_EOF) == STATE_EOF)){
            //printf("\n\r ---- EOF ---- \n\r");
            usleep(5000); // If we've reached EOF just continue to loop until the movie is closed or a seek is requested
            continue;
        }
        
        len = av_read_frame(c->p_format_ctx, &c->packet);   // Grab the next packet
        
        if ( unlikely(len < 0) ) {
            // If a negative number is returned, we've hit the EOF. Set the state and continue looping.
            c->play_state |= STATE_EOF;
            printf("\n\rvideo_inst.c::parseThread: Parse thread reached EOF.\n\r");
            continue;
        }
                if ( c->packet.stream_index == c->idx_audio_stream && v->audio.has_audio) {
            // Got an audio packet
            int err;
            decodedsize = DECODEBUF_SIZE;
            err = avcodec_decode_audio3(c->p_audio_ctx,pDecodeBuf, &decodedsize, &c->packet);
            
            while( (c->audio_ring.lock ||  c->audio_ring.count >= ABUF_SIZE) && !(c->play_state & STATE_DIE) && c->seek_req == 0) {
                usleep(100);
            }
            
            if(unlikely(c->seek_req > 0)) goto skip;
            if(unlikely((c->play_state & STATE_DIE) == STATE_DIE)) goto parse_thread_die;
            
            r = &c->audio_ring;
            pkt = &c->audio_buffer[r->write];
            limit = ABUF_SIZE;
        }
        else goto skip; // Got an unsupported packet; skip this packet and free it.
        
        if (decodedsize <= 0) goto skip;
        r->lock = kLocked;
        
        if(likely(pkt->data)){
            free(pkt->data);
            pkt->size=0;
            pkt->data=0L;
        }
        
        // Deep copy the packet into the buffer since the packet becomes invalidated next time 
        // av_read_frame is called.
        pkt->data           = (uint8_t*)calloc(1,decodedsize);
pkt->size           = decodedsize;
pkt->stream_index   = c->packet.stream_index;
pkt->flags          = c->packet.flags;
pkt->duration       = c->packet.duration;
pkt->pos            = c->packet.pos;
pkt->convergence_duration = c->packet.convergence_duration;
pkt->pts            = c->packet.pts;
pkt->dts            = c->packet.dts;
pkt->destruct       = c->packet.destruct;
pkt->priv           = &c->audio_buffer[c->audio_ring.write];
        
memcpy(pkt->data, pDecodeBuf, decodedsize);
                r->write++;
r->count++;
if(unlikely(r->write >= limit)) r->write %= limit;

r->lock = kUnlocked;
    skip:
        av_free_packet(&c->packet); // Free the packet.
        
    }
 
    pthread_exit(NULL);
parse_thread_die:
    printf("\n\rvideo_inst.c::parseThread: parse_thread_die reached.\n\r");
    av_free(pDecodeBuf);
    av_free_packet(&c->packet);
    pthread_exit(NULL);
}-- 设置Audio Queue --- (void) startPlayback
{
    OSStatus err = 0;
    if(playState.playing) return;    playState.started = false;    if(!playState.queue) 
    {        UInt32 bufferSize;        playState.format.mSampleRate = _av->audio.sample_rate;
        playState.format.mFormatID = kAudioFormatLinearPCM;
        playState.format.mFormatFlags = kAudioFormatFlagsCanonical;
        playState.format.mChannelsPerFrame = _av->audio.channels_per_frame;
        playState.format.mBytesPerPacket = sizeof(AudioSampleType) *_av->audio.channels_per_frame;
        playState.format.mBytesPerFrame = sizeof(AudioSampleType) *_av->audio.channels_per_frame;
        playState.format.mBitsPerChannel = 8 * sizeof(AudioSampleType);        playState.format.mFramesPerPacket = 1;        
        playState.format.mReserved = 0;
        pauseStart = 0;
        DeriveBufferSize(playState.format,playState.format.mBytesPerPacket,BUFFER_DURATION,&bufferSize,&numPacketsToRead);
        err= AudioQueueNewOutput(&playState.format, aqCallback, &playState, NULL, kCFRunLoopCommonModes, 0, &playState.queue);        if(err != 0)
        {
            printf("AQHandler.m startPlayback: Error creating new AudioQueue: %d \n", (int)err);
        }        for(int i = 0 ; i < NUM_BUFFERS ; i ++)
        {
            err = AudioQueueAllocateBufferWithPacketDescriptions(playState.queue, bufferSize, numPacketsToRead , &playState.buffers[i]);            if(err != 0)
                printf("AQHandler.m startPlayback: Error allocating buffer %d", i);
            fillAudioBuffer(&playState,playState.queue, playState.buffers[i]);
        }    }    startTime = mu_currentTimeInMicros();    err=AudioQueueStart(playState.queue, NULL);    if(err)
    {        char sErr[4];
        printf("AQHandler.m startPlayback: Could not start queue %ld %s.", err, FormatError(sErr,err));        playState.playing = NO;
    } 
    else
    {
        AudioSessionSetActive(true);
        playState.playing = YES;
    }           
}

解决方案 »

  1.   

    续上篇:-- AudioQueueOutputCallback : 读取audio raw写入AudioBuffer --//  
    int   getNextAudio(video_data_t* vInst, int maxlength, uint8_t* buf, int* pts, int* isDone) {
      
        struct video_context_t  *ctx = vInst->context;
        int    datalength            = 0;
     
        while(ctx->audio_ring.lock || (ctx->audio_ring.count <= 0 && ((ctx->play_state & STATE_DIE) != STATE_DIE))){
            
            if (ctx->play_state & STATE_EOF) return -1;        
            usleep(100);
        }
        
        *pts = 0;
        ctx->audio_ring.lock = kLocked;
        
        if(ctx->audio_ring.count>0 && maxlength > ctx->audio_buffer[ctx->audio_ring.read].size){
        
            memcpy(buf, ctx->audio_buffer[ctx->audio_ring.read].data, ctx->audio_buffer[ctx->audio_ring.read].size);
            
            *pts = ctx->audio_buffer[ctx->audio_ring.read].pts;
            
            datalength = ctx->audio_buffer[ctx->audio_ring.read].size;
            
            ctx->audio_ring.read++;        
            ctx->audio_ring.read %= ABUF_SIZE;        
            ctx->audio_ring.count--;
                 
        }
        ctx->audio_ring.lock = kUnlocked;
              
        if((ctx->play_state & STATE_EOF) == STATE_EOF && ctx->audio_ring.count == 0) *isDone = 1;
              
        return datalength;
    }//  AudioQueueOutputCallback
    static int ct = 0;
    static void fillAudioBuffer(void *info,AudioQueueRef queue, AudioQueueBufferRef buffer)
    {    int lengthCopied = INT32_MAX;
        int dts= 0;
        int isDone = 0;    buffer->mAudioDataByteSize = 0;
        buffer->mPacketDescriptionCount = 0;    OSStatus err = 0;
        AudioTimeStamp bufferStartTime;    AudioQueueGetCurrentTime(queue, NULL, &bufferStartTime, NULL);
        PlayState *ps = (PlayState *)info;    if (!ps->started)
            ps->started = true;    while(buffer->mPacketDescriptionCount < numPacketsToRead && lengthCopied > 0)
        {
            lengthCopied = getNextAudio(_av,
                            buffer->mAudioDataBytesCapacity-buffer->mAudioDataByteSize,
                            (uint8_t*)buffer->mAudioData+buffer->mAudioDataByteSize,
                            &dts,&isDone);        ct+= lengthCopied;        if(lengthCopied < 0 || isDone) 
            {
                printf("nothing to read....\n\n");
                PlayState *ps = (PlayState *)info;
                ps->finished = true;
                ps->started = false;
                break;
            }        if(aqStartDts < 0) aqStartDts = dts;        if(buffer->mPacketDescriptionCount ==0)
            {
                bufferStartTime.mFlags = kAudioTimeStampSampleTimeValid;
                bufferStartTime.mSampleTime = (Float64)(dts-aqStartDts);//* _av->audio.frame_size;            if (bufferStartTime.mSampleTime <0 ) 
                    bufferStartTime.mSampleTime = 0;            printf("AQHandler.m fillAudioBuffer: DTS for %x: %lf time base: %lf StartDTS: %d\n", 
                        (unsigned int)buffer, 
                        bufferStartTime.mSampleTime, 
                        _av->audio.time_base, 
                        aqStartDts);        }        buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mStartOffset = buffer->mAudioDataByteSize;
            buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mDataByteSize = lengthCopied;        buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mVariableFramesInPacket = 0;        buffer->mPacketDescriptionCount++;        buffer->mAudioDataByteSize += lengthCopied;
        }    int audioBufferCount, audioBufferTotal,  videoBufferCount, videoBufferTotal;
        bufferCheck(_av,&videoBufferCount, &videoBufferTotal, &audioBufferCount, &audioBufferTotal);    if(buffer->mAudioDataByteSize)
        {        err = AudioQueueEnqueueBufferWithParameters(queue, buffer, 0, NULL, 0, 0, 0, NULL, &bufferStartTime, NULL);        if(err)
            {
                char sErr[10];
                printf("AQHandler.m fillAudioBuffer: Could not enqueue buffer 0x%x: %d %s.", buffer, err, FormatError(sErr, err));        }    }}
      

  2.   

    回去研究下ffmpeg, 学习下