/* this is called for each file to process */ enum codec_status codec_run(void) { size_t n; unsigned char *filebuf; int sample_loc; intptr_t param; if (codec_init()) return CODEC_ERROR; ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); codec_set_replaygain(ci->id3); /* Intialise the A52 decoder and check for success */ state = a52_init(0); samplesdone = 0; /* The main decoding loop */ if (ci->id3->offset) { if (ci->seek_buffer(ci->id3->offset)) { samplesdone = (ci->id3->offset / ci->id3->bytesperframe) * A52_SAMPLESPERFRAME; ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000)); } } else { ci->seek_buffer(ci->id3->first_frame_offset); ci->set_elapsed(0); } while (1) { enum codec_command_action action = ci->get_command(¶m); if (action == CODEC_ACTION_HALT) break; if (action == CODEC_ACTION_SEEK_TIME) { sample_loc = param/1000 * ci->id3->frequency; if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) { samplesdone = sample_loc; ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); } ci->seek_complete(); } filebuf = ci->request_buffer(&n, BUFFER_SIZE); if (n == 0) /* End of Stream */ break; a52_decode_data(filebuf, filebuf + n); ci->advance_buffer(n); } return CODEC_OK; }
/* this is the codec entry point */ enum codec_status codec_main(void) { size_t n; unsigned char *filebuf; int sample_loc; int retval; /* Generic codec initialisation */ ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); ci->configure(DSP_SET_SAMPLE_DEPTH, 28); next_track: retval = CODEC_OK; if (codec_init()) { retval = CODEC_ERROR; goto exit; } if (codec_wait_taginfo() != 0) goto request_next_track; ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); codec_set_replaygain(ci->id3); /* Intialise the A52 decoder and check for success */ state = a52_init(0); /* The main decoding loop */ if (ci->id3->offset) { if (ci->seek_buffer(ci->id3->offset)) { samplesdone = (ci->id3->offset / ci->id3->bytesperframe) * A52_SAMPLESPERFRAME; ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000)); } } else { samplesdone = 0; } while (1) { if (ci->stop_codec || ci->new_track) break; if (ci->seek_time) { sample_loc = (ci->seek_time - 1)/1000 * ci->id3->frequency; if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) { samplesdone = sample_loc; ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); } ci->seek_complete(); } filebuf = ci->request_buffer(&n, BUFFER_SIZE); if (n == 0) /* End of Stream */ break; a52_decode_data(filebuf, filebuf + n); ci->advance_buffer(n); } request_next_track: if (ci->request_next_track()) goto next_track; exit: a52_free(state); return retval; }
void* audio_write_start(void *arg) { int idle = 1; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int len; sigset_t sigs; demux_attr_t *attr; video_info_t *vi; signal(SIGURG, sighandler); sigemptyset(&sigs); sigaddset(&sigs, SIGURG); pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); pthread_mutex_lock(&mutex); printf("audio write thread started (pid %d)\n", getpid()); pthread_cond_wait(&video_cond, &mutex); while (1) { while (seeking || jumping) pthread_cond_wait(&video_cond, &mutex); while (!video_playing) { pcm_decoded = 0; empty_ac3(); if ( !(idle) ) { sem_post(&write_threads_idle_sem); idle = 1; printf("audio write thread sleeping...\n"); } pthread_cond_wait(&video_cond, &mutex); } if ( idle ) { sem_wait(&write_threads_idle_sem); idle = 0; printf("audio write thread running\n"); } if (running_replaytv) { attr = demux_get_attr(handle); vi = &attr->video.stats.info.video; if (attr->audio.type != audio_type) { // JBH: FIX ME: This code never gets hit audio_type = attr->audio.type; switch (audio_type) { case AUDIO_MODE_AC3: case AUDIO_MODE_PCM: audio_output = AV_AUDIO_PCM; printf("switch to PCM audio\n"); break; default: av_set_audio_type(audio_type); audio_output = AV_AUDIO_MPEG; printf("switch to MPEG audio\n"); break; } av_set_audio_output(audio_output); } } switch (audio_type) { case AUDIO_MODE_MPEG1_PES: case AUDIO_MODE_MPEG2_PES: case AUDIO_MODE_ES: if (jit_mode == 0) { if ((len=DEMUX_WRITE_AUDIO(handle, fd_audio)) > 0) pthread_cond_broadcast(&video_cond); else pthread_cond_wait(&video_cond, &mutex); } else { int flags, duration; len=DEMUX_JIT_WRITE_AUDIO(handle, fd_audio, get_cur_vid_stc(),jit_mode, &flags,&duration); if(flags & 4) { /*4 is the same as 1 followed by 2*/ flags = (flags | 1 | 2) & ~4; } if(flags & 1) { av_pause_video(); } if((flags & 2) && !paused) { if(duration <= 10) video_unpause_timer_callback(pause_widget); else mvpw_set_timer(pause_widget, video_unpause_timer_callback, duration); } if(flags & 8) { usleep(duration*1000); } if(len > 0) pthread_cond_broadcast(&video_cond); else if(!(flags & 8)) pthread_cond_wait(&video_cond, &mutex); } break; case AUDIO_MODE_PCM: /* * XXX: PCM audio does not work yet */ pthread_cond_wait(&video_cond, &mutex); break; case AUDIO_MODE_AC3: if (audio_output_mode == AUD_OUTPUT_PASSTHRU ) { if ((len=DEMUX_WRITE_AUDIO(handle, fd_audio)) > 0) pthread_cond_broadcast(&video_cond); else pthread_cond_wait(&video_cond, &mutex); break; } if (ac3more == -1) ac3more = a52_decode_data(NULL, NULL, pcm_decoded); if (ac3more == 1) { ac3more = a52_decode_data(ac3buf, ac3buf + ac3len, pcm_decoded); if (ac3more == 1) { pthread_cond_wait(&video_cond, &mutex); break; } } if (ac3more == 0) { ac3len = demux_get_audio(handle, ac3buf, sizeof(ac3buf)); ac3more = 1; } if (ac3more == 0) pthread_cond_wait(&video_cond, &mutex); else pthread_cond_broadcast(&video_cond); pcm_decoded = 1; break; } } return NULL; }
/* this is called for each file to process */ enum codec_status codec_run(void) { size_t n; uint8_t *filebuf; int consumed, packet_offset; int playback_on = -1; size_t resume_offset; intptr_t param; enum codec_command_action action = CODEC_ACTION_NULL; if (codec_init()) { return CODEC_ERROR; } resume_offset = ci->id3->offset; ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); codec_set_replaygain(ci->id3); ci->seek_buffer(ci->id3->first_frame_offset); /* Intializations */ state = a52_init(0); ci->memset(&rmctx,0,sizeof(RMContext)); ci->memset(&pkt,0,sizeof(RMPacket)); init_rm(&rmctx); samplesdone = 0; /* check for a mid-track resume and force a seek time accordingly */ if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; /* put number of subpackets to skip in resume_offset */ resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); action = CODEC_ACTION_SEEK_TIME; } else { /* Seek to the first packet */ ci->set_elapsed(0); ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE ); } /* The main decoding loop */ while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) { if (action == CODEC_ACTION_NULL) action = ci->get_command(¶m); if (action == CODEC_ACTION_HALT) break; if (action == CODEC_ACTION_SEEK_TIME) { packet_offset = param / ((rmctx.block_align*8*1000)/rmctx.bit_rate); ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE)); rmctx.audio_pkt_cnt = packet_offset; samplesdone = (rmctx.sample_rate/1000 * param); ci->set_elapsed(samplesdone/(frequency/1000)); ci->seek_complete(); } action = CODEC_ACTION_NULL; filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE); consumed = rm_get_packet(&filebuf, &rmctx, &pkt); if(consumed < 0 && playback_on != 0) { if(playback_on == -1) { /* Error only if packet-parsing failed and playback hadn't started */ DEBUGF("rm_get_packet failed\n"); return CODEC_ERROR; } else { break; } } playback_on = 1; a52_decode_data(filebuf, filebuf + rmctx.block_align); ci->advance_buffer(pkt.length); } return CODEC_OK; }