2013-02-27 3 views
0

У меня есть видеопроигрыватель в моем приложении. У меня нет проблем с файлами avi и mp3-аудио, но когда я играю в mpg или wmv, и мне приходится использовать avcodec_decode_audio3. Первые секунды воспроизводятся, а затем, когда заполняется буфер, я получаю тишину в течение нескольких секунд, а затем звук продолжается с одного и того же места, это происходит каждый раз, когда буфер заполняется.FFmpeg: аудиосинхронизация с звуковым сигналом

Это звуковых сообщений Формат:

 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; 

fillAudioBuffer:

static void fillAudioBuffer(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); 

while(buffer->mPacketDescriptionCount < numPacketsToRead && lengthCopied > 0){ 

    lengthCopied = getNextAudio(_av,buffer->mAudioDataBytesCapacity-buffer->mAudioDataByteSize, (uint8_t*)buffer->mAudioData+buffer->mAudioDataByteSize,&dts,&isDone); 
    if(!lengthCopied || isDone) break; 

    if(aqStartDts < 0) aqStartDts = dts; 
    if(buffer->mPacketDescriptionCount ==0){ 
     bufferStartTime.mFlags = kAudioTimeStampSampleTimeValid; 
     bufferStartTime.mSampleTime = (Float64)(dts-aqStartDts); 
    } 
    buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mStartOffset = buffer->mAudioDataByteSize; 
    buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mDataByteSize = lengthCopied; 
    buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mVariableFramesInPacket = _av->audio.frame_size; 
    buffer->mPacketDescriptionCount++; 
    buffer->mAudioDataByteSize += lengthCopied; 

} 
if(buffer->mAudioDataByteSize){ 
    if((err=AudioQueueEnqueueBufferWithParameters(queue, buffer, 0, NULL, 0, 0, 0, NULL, &bufferStartTime, NULL))) 
    { 

    } 
} 


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))&&((ctx->play_state & STATE_EOF) != STATE_EOF))){ 
    PMSG1(stdout,"die get audio %d", ctx->play_state); 
    if((ctx->play_state & STATE_STOP) != STATE_STOP){ 
     PMSG1(stdout,"die NO CARGADO %d",ctx->play_state); 
     return 0; 
    } 
    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); 
    datalength = ctx->audio_buffer[ctx->audio_ring.read].size; 
    *pts = ctx->audio_buffer[ctx->audio_ring.read].pts; 
    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; 

Это журнал играет файл миль на галлон:

Input #0, mpeg, '1.MPG': 
    Duration: 00:03:14.74, start: 3370.475789, bitrate: 2489 kb/s 
    Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p, 544x576 [SAR 24:17 DAR 4:3], 9000 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc 
    Stream #0:1[0x1c0]: Audio: mp2, 48000 Hz, stereo, s16, 192 kb/s 
mpeg2video MPEG-2 video 
aspect 1.333333 
startPlayback 
DTS: 0.000000 time base: 0.000011 StartDTS: 303347520 Orig DTS: 303347520 
Video Buffer: 157/1024 Audio Buffer: 33/1024 
Bytes copied for buffer 0xc292ac0: 1046016 
DTS: 490320.000000 time base: 0.000011 StartDTS: 303347520 Orig DTS: 303837840 
Video Buffer: 276/1024 Audio Buffer: 2/1024 
Bytes copied for buffer 0x1225f8b0: 1046016 
DTS: 980640.000000 time base: 0.000011 StartDTS: 303347520 Orig DTS: 304328160 
Video Buffer: 411/1024 Audio Buffer: 1/1024 
Bytes copied for buffer 0x13380840: 1046016 
DTS: 1470960.000000 time base: 0.000011 StartDTS: 303347520 Orig DTS: 304818480 
Video Buffer: 885/1024 Audio Buffer: 797/1024 
Bytes copied for buffer 0xc292ac0: 1046016 
-----Here the audio stop for 4 or 5 seconds 
-----then continues for 4 or 5 seconds 
DTS: 1961280.000000 time base: 0.000011 StartDTS: 303347520 Orig DTS: 305308800 
Video Buffer: 765/1024 Audio Buffer: 797/1024 
Bytes copied for buffer 0x1225f8b0: 1046016 
-----Here the audio stop for 4 or 5 seconds 
-----then continues for 4 or 5 seconds 
DTS: 2451600.000000 time base: 0.000011 StartDTS: 303347520 Orig DTS: 305799120 
Video Buffer: 644/1024 Audio Buffer: 798/1024 
Bytes copied for buffer 0x13380840: 1046016 
... 

если я уменьшить буфер, тишина и время звучания уменьшается. Итак, я хочу знать, как это исправить? Благодаря!!

+0

Вы уверены, что аудио буфер достаточно большой, если (buffer-> mAudioDataByteSize) { если ((ERR = AudioQueueEnqueueBufferWithParameters (очередь, буфер, 0, NULL, 0, 0, 0, NULL, & bufferStartTime, NULL))) возможно, взгляните на этот https://github.com/mooncatventures-group/sampleDecoder { } } –

+0

Я попытался увеличить буфер без везения. Спасибо за этот код. Я стараюсь сделать это как этот код, но у меня все еще есть одна и та же проблема, и интересно, что молчание - это такое же количество времени, что и звук. Дело в том, что этот код заключается в том, что он игнорирует точки, это нормально только для воспроизведения звука, но если я так делаю, то получаю десинхронизированное аудио/видео. – juanramoney

+0

Возможно, проблема с реализацией вашего буфера буфера –

ответ

0

У меня есть аналогичная проблема, хотя и не совсем то же самое. Я даже не уверен, что iOS смотрит на mSampleTime (нужно поэкспериментировать с этим), но одна вещь, которая выпрыгивает на меня, заключается в том, что mSampleTime не является единицей времени, но она находится в единицах выборок. Вместо

if(buffer->mPacketDescriptionCount ==0){ 
    bufferStartTime.mFlags = kAudioTimeStampSampleTimeValid; 
    bufferStartTime.mSampleTime = (Float64)(dts-aqStartDts); 
} 

Чтобы установить bufferStartTime, я использую следующие:

AudioTimeStamp presentationTime = { 0 }; 
AudioTimeStamp actualStartTime = { 0 }; 

presentationTime.mFlags = kAudioTimeStampSampleTimeValid; 
presentationTime.mSampleTime = (Float64) (block->presentationTime/(Float64) 1000000000.0) * (Float64) format.mSampleRate; 

AudioQueueEnqueueBufferWithParameters(output, buffer, 0, NULL, trimFramesStart, trimFramesEnd, 0, NULL, &presentationTime, &actualStartTime); 

Конечно выше фрагменты кода refferences структуры данных Я не задающие здесь (я не определяя мой объект блока, а preseentationTime - в nano seconds). Опять же, мне кажется, что у меня есть время, когда вы читаете время из аудио очереди через AudioQueueGetCurrentTime (синхронизация видео с этой эффективной позицией в аудио, похоже, крошечное постоянное смещение, которое со временем связывает A/V-десинхронизацию для меня). Еще не играл с другими аудиоформатами.

Смежные вопросы