GF_EXPORT u32 gf_ringbuffer_read(GF_Ringbuffer *rb, u8 *dest, u32 szDest) { u32 free_sz, sz2, to_read, n1, n2; if ((free_sz = gf_ringbuffer_available_for_read(rb)) == 0) { return 0; } to_read = szDest > free_sz ? free_sz : szDest; sz2 = rb->read_ptr + to_read; if (sz2 > rb->size) { n1 = rb->size - rb->read_ptr; n2 = sz2 & rb->size_mask; } else { n1 = to_read; n2 = 0; } memcpy (dest, &(rb->buf[rb->read_ptr]), n1); rb->read_ptr += n1; rb->read_ptr &= rb->size_mask; if (n2) { memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2); rb->read_ptr += n2; rb->read_ptr &= rb->size_mask; } return to_read; }
/** * This thread sends the frame to TS mux * \param Parameter The GF_AVRedirect pointer */ static Bool audio_encoding_thread_run(void *param) { u8 * inBuff; u8 * outBuff; u32 inBuffSize, outBuffSize, samplesReaden, toRead; u64 myTime = 0; u32 frameCountSinceReset = 0; u32 lastCurrentTime; Bool sendPts = 1; GF_AVRedirect * avr = (GF_AVRedirect*) param; AVCodecContext * ctx = NULL; assert( avr ); outBuffSize = FF_MIN_BUFFER_SIZE; outBuff = gf_malloc(outBuffSize* sizeof(u8)); inBuff = NULL; #ifdef DUMP_MP3 FILE * mp3 = fopen("/tmp/dump.mp3", "w"); #endif /* DUMP_MP3 */ sendPts = 1; gf_sc_add_audio_listener ( avr->term->compositor, &avr->audio_listen ); while (avr->is_running && !ctx) { ctx = ts_get_audio_codec_context(avr->ts_implementation); gf_sleep(16); } if (!ctx) { goto exit; } printf("******* Audio Codec Context = %d/%d, start="LLU", frame_size=%u\n", ctx->time_base.num, ctx->time_base.den, ctx->timecode_frame_start, ctx->frame_size); samplesReaden = ctx->frame_size * ctx->channels; //printf("SETUP input sample size=%u, output samplesize=%u, buffsize=%u, samplesReaden=%u\n", ctx->input_sample_size, ctx->frame_size, sizeof(outbuf), samplesReaden); // 2 chars are needed for each short toRead = samplesReaden * 2; inBuffSize = toRead; inBuff = gf_malloc(inBuffSize * sizeof(u8)); while (avr->is_running && !avr->audioCurrentTime) { gf_sleep(16); } myTime = lastCurrentTime = avr->audioCurrentTime; frameCountSinceReset = 0; while (avr->is_running) { u32 readen; if (U32_ABS(avr->audioCurrentTime, myTime) > 25000) { //GF_LOG( GF_LOG_ERROR, GF_LOG_MODULE, ("[AVRedirect] Drift in audio : audioCurrentTime = %u, myTime=%u, resync...\n", avr->audioCurrentTime, myTime)); //myTime = lastCurrentTime = avr->audioCurrentTime; //frameCountSinceReset = 0; sendPts = 1; } while (toRead <= gf_ringbuffer_available_for_read(avr->pcmAudio) ) { memset( inBuff, 0, inBuffSize); memset( outBuff, 0, outBuffSize); readen = gf_ringbuffer_read(avr->pcmAudio, inBuff, toRead); assert( readen == toRead ); if (avr->encode) { //u32 oldFrameSize = ctx->frame_size; //ctx->frame_size = readable / (2 * ctx->channels); //assert( oldFrameSize <= ctx->frame_size ); /* buf_size * input_sample_size / output_sample_size */ int encoded = avcodec_encode_audio(ctx, outBuff, outBuffSize, (const short *) inBuff); if (encoded < 0) { GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[RedirectAV]: failed to encode audio, buffer size=%u, readen=%u, frame_size=%u\n", outBuffSize, readen, ctx->frame_size)); } else if (encoded > 0) { ts_encode_audio_frame(avr->ts_implementation, outBuff, encoded, sendPts ? myTime : AV_NOPTS_VALUE ); frameCountSinceReset++; #ifdef DUMP_MP3 fwrite( outBuff, sizeof(char), encoded, mp3); #endif /* DUMP_MP3 */ //if (ctx->codec->id == CODEC_ID_MP3) { /* It seems the MP3 codec only fetches 50% of data... */ // myTime= lastCurrentTime + (frameCountSinceReset * ctx->frame_size * 500 / ctx->sample_rate); //} else //myTime = lastCurrentTime + (frameCountSinceReset * toRead * 1000 / ctx->sample_rate/ ctx->channels / 4); /* Avoid overflow , multiply by 10 and divide sample rate by 100 instead of *1000 / sampleRate */ myTime = lastCurrentTime + (frameCountSinceReset * toRead * 10 / (ctx->sample_rate / 100) / ctx->channels / 4); //sendPts = 0; sendPts = 1; } else { GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[RedirectAV]: no encoded frame.\n")); //frameCountSinceReset++; } //ctx->frame_size = oldFrameSize; } } gf_sleep(1); } exit: GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[AVRedirect] Ending audio encoding thread...\n")); if (inBuff) gf_free( inBuff ); if (outBuff) gf_free( outBuff ); #ifdef DUMP_MP3 if (mp3) fclose(mp3); #endif /* DUMP_MP3 */ if (avr->term) gf_sc_remove_audio_listener ( avr->term->compositor, &avr->audio_listen ); return GF_OK; }