bool ReadMedia::getLoop() { bool tmp = true; lockState(); if (m_file && bgav_can_seek( m_file) ) { tmp = m_loop; } else { tmp = false; // we can't loop on file, return false // but leave the loop var untouched } unlockState(); return tmp; }
bool ReadMedia::pcmSeek( int64_t samples ) { lockState(); if (m_state == STATE_READY && m_file && bgav_can_seek( m_file) && samples >= 0 && samples < m_num_samples ) { m_pcm_seek = samples; unlockState(); signalAV(); return true; } else { m_pcm_seek = SEEK_NOTHING; unlockState(); return false; } }
bool ReadMedia::timeSeek(double seconds) { gavl_time_t gt = gavl_seconds_to_time( seconds ) ; lockState(); if (m_state == STATE_READY && m_file && bgav_can_seek( m_file) && seconds >= 0.0 && seconds < m_length_in_seconds ) { if (m_audio_stream_count) { m_pcm_seek = gavl_time_to_samples(m_audio_format.samplerate, gt ); if (m_pcm_seek >= m_num_samples || m_pcm_seek < 0) m_pcm_seek = SEEK_NOTHING; unlockState(); signalAV(); return true; } else if ( m_video_stream_count && m_video_format.framerate_mode == GAVL_FRAMERATE_CONSTANT ) { m_frame_seek = gavl_time_to_frames( m_video_format.timescale, m_video_format.frame_duration, gt ); if (m_frame_seek >= m_num_frames || m_frame_seek < 0 ) m_frame_seek = SEEK_NOTHING; unlockState(); signalAV(); return true; } } unlockState(); return false; }
int bg_avdec_init(avdec_priv * avdec) { int i; const bgav_metadata_t * m; const gavl_chapter_list_t * cl; gavl_time_t duration; avdec->num_tracks = bgav_num_tracks(avdec->dec); avdec->track_info = calloc(avdec->num_tracks, sizeof(*(avdec->track_info))); for(i = 0; i < avdec->num_tracks; i++) { avdec->track_info[i].num_audio_streams = bgav_num_audio_streams(avdec->dec, i); avdec->track_info[i].num_video_streams = bgav_num_video_streams(avdec->dec, i); avdec->track_info[i].num_text_streams = bgav_num_text_streams(avdec->dec, i); avdec->track_info[i].num_overlay_streams = bgav_num_overlay_streams(avdec->dec, i); if(bgav_can_seek(avdec->dec)) avdec->track_info[i].flags |= BG_TRACK_SEEKABLE; if(bgav_can_pause(avdec->dec)) avdec->track_info[i].flags |= BG_TRACK_PAUSABLE; if(avdec->track_info[i].num_audio_streams) { avdec->track_info[i].audio_streams = calloc(avdec->track_info[i].num_audio_streams, sizeof(*avdec->track_info[i].audio_streams)); } if(avdec->track_info[i].num_video_streams) { avdec->track_info[i].video_streams = calloc(avdec->track_info[i].num_video_streams, sizeof(*avdec->track_info[i].video_streams)); } if(avdec->track_info[i].num_text_streams) { avdec->track_info[i].text_streams = calloc(avdec->track_info[i].num_text_streams, sizeof(*avdec->track_info[i].text_streams)); } if(avdec->track_info[i].num_overlay_streams) { avdec->track_info[i].overlay_streams = calloc(avdec->track_info[i].num_overlay_streams, sizeof(*avdec->track_info[i].overlay_streams)); } duration = bgav_get_duration(avdec->dec, i); if(duration != GAVL_TIME_UNDEFINED) gavl_metadata_set_long(&avdec->track_info[i].metadata, GAVL_META_APPROX_DURATION, duration); /* Get metadata */ m = bgav_get_metadata(avdec->dec, i); gavl_metadata_copy(&avdec->track_info[i].metadata, m); /* Get chapters */ cl = bgav_get_chapter_list(avdec->dec, i); if(cl) { avdec->track_info[i].chapter_list = gavl_chapter_list_copy(cl); bg_chapter_list_set_default_names(avdec->track_info[i].chapter_list); } } return 1; }
void *the_videofifo_filler( void * xp) { ReadMedia *rm = (ReadMedia *)xp; int ret = 0; int first = true; int doaudio = rm->getAudioStreamCount(); int64_t seekto =SEEK_NOTHING; int can_seek = bgav_can_seek ( rm->getFile() ); int can_seek_sample = bgav_can_seek_sample ( rm->getFile() ); int timescale = rm->getVideoTimescale(); while (!rm->quitAVThreads() ) { while ( rm->getVideoFifo() !=NULL && rm->getVideoFifo()->FreeSpace() && !rm->getVEOF() ) { if (rm->quitAVThreads() ) pthread_exit(NULL);//return NULL; rm->lockAV(); // check to see if we need to seek // if this is set, we already know we can seek on this file // and don't need to check with bgav_can_seek if (can_seek) { seekto = rm->frameSeek(); if ( seekto >= 0 ) { if (doaudio && rm->getAudioFifo() ) rm->getAudioFifo()->Flush(); rm->getVideoFifo()->Flush(); bgav_seek_scaled(rm->getFile(), &seekto, timescale); } else if (seekto == SEEK_REWIND && !doaudio) { // rewind is a special case for Video. rm->getVideoFifo()->Flush(); seekto =0; bgav_seek_scaled(rm->getFile(), &seekto, timescale); } } ret = bgav_read_video(rm->getFile(), rm->getVideoFrame(), 0 ); if ( !ret ) { // only loop from video if there is no audio // audio controls loop timing if ( rm->getLoop() ){ if ( can_seek ) { if (doaudio && can_seek_sample) { // seek on video stream only if we have audio // audio and video seeking are separate in sample accurate // seeking. If no sample accurate seeking, then let audio // handle seeking bgav_seek_video(rm->getFile(), 0,0); } else if (!doaudio) { // if we don't have audio...just seek to 0 seekto=0; bgav_seek_scaled(rm->getFile(), &seekto, timescale); } } else { // if (can_seek) printf ("We want to loop video, but we cannot seek on this video stream,setting VEOF\n"); rm->setVEOF(true); } } else { rm->setVEOF(true); } rm->unlockAV(); break; } rm->unlockAV(); if( !rm->getVideoFifo()->Append( rm->getVideoFrame() )) printf("problem with appending VideoFrame\n"); } // on the first time 'round we will call the open callback // if there is no video in the file, the audio will handle it. if (first) { rm->setState( STATE_READY ); rm->callOpenCallback(); first = false; } if (rm->quitAVThreads() ) pthread_exit(NULL); //return NULL; rm->waitV(); } pthread_exit(NULL); //return NULL; }
void *the_audiofifo_filler( void * xp) { int samples_returned=0; ReadMedia *rm = (ReadMedia *)xp; int first = true; int dovideo = rm->getVideoStreamCount(); int spf = rm->getSamplesPerFrame(); int samplerate = rm->getAudioSamplerate(); int64_t seekto = SEEK_NOTHING; int can_seek = bgav_can_seek ( rm->getFile() ); int can_seek_sample = bgav_can_seek_sample ( rm->getFile() ); while ( !rm->quitAVThreads() ) { //while ( rm->getAudioFifo() != NULL && rm->getAudioFifo()->FreeSpace() && !rm->getAEOF() ) { while ( rm->getAudioFifo()->FreeSpace() && !rm->getAEOF() ) { if (rm->quitAVThreads() ) pthread_exit(NULL) ; //return NULL; rm->lockAV(); // check to see if we need to seek // if this is set, we already know we can seek on this file // and don't need to check with bgav_can_seek if ( can_seek ) { seekto = rm->pcmSeek(); if ( seekto != SEEK_NOTHING ) { if ( seekto == SEEK_REWIND) { // bgav_seek_audio ONLY seeks on the audio stream seekto = 0; // bgav_seek_scaled(rm->getFile(), &seekto, samplerate); } //else { bgav_seek_scaled(rm->getFile(), &seekto, samplerate); //} rm->getAudioFifo()->Flush(); if (dovideo && rm->getVideoFifo() ) { rm->getVideoFifo()->Flush(); rm->signalV(); } } } samples_returned = bgav_read_audio(rm->getFile(), rm->getAudioFrame(), 0, spf ); //rm->unlockAV(); if (samples_returned == 0 ) { if( rm->getLoop() ) { if ( can_seek ) { // Now, rewind the file, don't flush the fifo's if (can_seek_sample) { // only seek on audio stream bgav_seek_audio(rm->getFile(), 0, 0); } else { seekto =0; bgav_seek_scaled(rm->getFile(), &seekto, samplerate); if (dovideo && rm->getVideoFifo() ) { rm->setVEOF(false); rm->signalV(); } } // SAVE THIS FOR ANOTHER TIME, OVERLAPPED SMOOTH LOOPING //if ( rm->getLoop() > 1 && bgav_read_audio(rm->getFile(), rm->getAudioFrame(), 0, spf ) ) { // add to the fifo, overlapping // rm->getAudioFifo()->AppendOverlap( rm->getAudioFrame(), 5 ); // } } else { // this file is not seekable, what do we do? printf("cannot seek on file, but we want to loop. setting end of file.\n"); rm->setAEOF(true); } } else { rm->setAEOF(true); } rm->unlockAV(); break; } rm->unlockAV(); if( !rm->getAudioFifo()->Append( rm->getAudioFrame() )) printf("problem with appending Audio Frame\n"); } if (first && !dovideo) { rm->setState( STATE_READY ); rm->callOpenCallback(); first = false; } if (rm->quitAVThreads() ) pthread_exit(NULL); //return NULL; rm->waitA(); } pthread_exit(NULL);//return NULL; }