static void sfsamples_bang(t_sfsamples *x) { DEBUG(post("sfsamples_bang")); const gavl_audio_format_t* open_audio_format; gavl_time_t gavl_time; if(x->filename == &s_) { pd_error(x,"no file set"); return; } if(!bgav_open(x->decoder, x->filename->s_name)) { pd_error(x, "Could not open file %s", x->filename->s_name); } // only concerned with the first audio stream open_audio_format = bgav_get_audio_format(x->decoder, 0); // we can get audio formats that are unkown if (open_audio_format->sample_format == GAVL_SAMPLE_NONE) { pd_error(x, "sorry, this file has unsupported audio."); } gavl_time = bgav_get_duration(x->decoder, 0); outlet_float(x->x_obj.ob_outlet, (float)(gavl_time_to_samples(open_audio_format->samplerate, gavl_time) / (float)open_audio_format->samplerate)); }
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; }
static snd_pcm_t * bg_alsa_open(const char * card, gavl_audio_format_t * format, snd_pcm_stream_t stream, gavl_time_t buffer_time, int * convert_4_3) { unsigned int i_tmp; int dir, err; snd_pcm_hw_params_t *hw_params = NULL; // snd_pcm_sw_params_t *sw_params = NULL; snd_pcm_t *ret = NULL; snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t period_size; snd_pcm_uframes_t period_size_min = 0; snd_pcm_uframes_t period_size_max = 0; snd_pcm_uframes_t buffer_size_min = 0; snd_pcm_uframes_t buffer_size_max = 0; /* We open in non blocking mode so our process won't hang if the card is busy */ if((err = snd_pcm_open(&ret, card, stream, // SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_CAPTURE SND_PCM_NONBLOCK // SND_PCM_ASYNC ) < 0)) { ret = NULL; bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_open failed for device %s (%s)", card, snd_strerror(err)); goto fail; } /* Now, set blocking mode */ snd_pcm_nonblock(ret, 0); if(snd_pcm_hw_params_malloc(&hw_params) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_malloc failed"); goto fail; } if(snd_pcm_hw_params_any(ret, hw_params) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_any failed"); goto fail; } /* Interleave mode */ if(snd_pcm_hw_params_set_access(ret, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_access failed"); goto fail; } else format->interleave_mode = GAVL_INTERLEAVE_ALL; /* Sample format */ switch(format->sample_format) { case GAVL_SAMPLE_S8: case GAVL_SAMPLE_U8: if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S8) < 0) // if(1) { /* Soundcard support no 8-bit, try 16 */ if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; } else format->sample_format = GAVL_SAMPLE_S8; break; case GAVL_SAMPLE_S16: case GAVL_SAMPLE_U16: if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; break; case GAVL_SAMPLE_S32: #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_BE) < 0) #endif { /* Soundcard supports no 32-bit, try 24 (more probably supported but needs conversion) */ #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3BE) < 0) #endif { /* No 24 bit, try 16 */ if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; } else { format->sample_format = GAVL_SAMPLE_S32; if(convert_4_3) *convert_4_3 = 1; } } else format->sample_format = GAVL_SAMPLE_S32; break; case GAVL_SAMPLE_FLOAT: case GAVL_SAMPLE_DOUBLE: if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_FLOAT) < 0) { #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_BE) < 0) #endif { /* Soundcard supports no 32-bit, try 24 (more probably supported but needs conversion) */ #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3BE) < 0) #endif { /* No 24 bit, try 16 */ if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; } else { format->sample_format = GAVL_SAMPLE_S32; if(convert_4_3) *convert_4_3 = 1; } } else format->sample_format = GAVL_SAMPLE_S32; } else format->sample_format = GAVL_SAMPLE_FLOAT; break; case GAVL_SAMPLE_NONE: goto fail; break; } /* Channels */ if(snd_pcm_hw_params_set_channels(ret, hw_params, format->num_channels) < 0) { if(format->num_channels == 1) /* Mono doesn't work, try stereo */ { if(snd_pcm_hw_params_set_channels(ret, hw_params, 2) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_channels failed (Format has %d channels)", format->num_channels); goto fail; } else { format->num_channels = 2; format->channel_locations[0] = GAVL_CHID_FRONT_LEFT; format->channel_locations[1] = GAVL_CHID_FRONT_RIGHT; } } else { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_channels failed (Format has %d channels)", format->num_channels); goto fail; } } /* Switch off driver side resampling */ #if SND_LIB_VERSION >= 0x010009 snd_pcm_hw_params_set_rate_resample(ret, hw_params, 0); #endif /* Samplerate */ i_tmp = format->samplerate; if(snd_pcm_hw_params_set_rate_near(ret, hw_params, &i_tmp, 0) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_rate_near failed"); goto fail; } if(format->samplerate != i_tmp) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Samplerate %d not supported by device %s, using %d", format->samplerate, card, i_tmp); } format->samplerate = i_tmp; dir = 0; /* Buffer size */ snd_pcm_hw_params_get_buffer_size_min(hw_params, &buffer_size_min); snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size_max); dir=0; snd_pcm_hw_params_get_period_size_min(hw_params, &period_size_min,&dir); dir=0; snd_pcm_hw_params_get_period_size_max(hw_params, &period_size_max,&dir); buffer_size = gavl_time_to_samples(format->samplerate, buffer_time); if(buffer_size > buffer_size_max) buffer_size = buffer_size_max; if(buffer_size < buffer_size_min) buffer_size = buffer_size_min; period_size = buffer_size / 8; buffer_size = period_size * 8; dir = 0; if(snd_pcm_hw_params_set_period_size_near(ret, hw_params, &period_size, &dir) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_period_size failed"); goto fail; } dir = 0; snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir); dir = 0; if(snd_pcm_hw_params_set_buffer_size_near(ret, hw_params, &buffer_size) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_buffer_size failed"); goto fail; } snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size); format->samples_per_frame = period_size; /* Write params to card */ if(snd_pcm_hw_params (ret, hw_params) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params failed"); goto fail; } snd_pcm_hw_params_free(hw_params); gavl_set_channel_setup(format); // gavl_audio_format_dump(format); return ret; fail: bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Alsa initialization failed"); if(ret) snd_pcm_close(ret); if(hw_params) snd_pcm_hw_params_free(hw_params); return NULL; }
bool ReadMedia::initFormat() { const gavl_audio_format_t * open_audio_format; const gavl_video_format_t * open_video_format; // we use the m_vfifosize to see if the user app wants video or not // then, we set m_video_stream_count to 0 if he doesn't want video if (m_video_stream_count > 0 && m_vfifosize > 0) { open_video_format = bgav_get_video_format(m_file, 0); if (open_video_format->pixelformat == GAVL_PIXELFORMAT_NONE) { printf("!!!sorry, pixelformat is not recognized.\n"); return false; } // let's check to see if the formats are the same, if they are the same // there is no reason to recreate the fifo or frames if ( gavl_video_formats_equal( &m_video_format, open_video_format) == 0 ) { // the formats are different gavl_video_format_copy (&m_video_format, open_video_format); if (m_video_frame != NULL) gavl_video_frame_destroy(m_video_frame); m_video_frame = gavl_video_frame_create(&m_video_format); gavl_video_frame_clear( m_video_frame, &m_video_format); if (m_fifovideo != NULL) delete m_fifovideo; m_fifovideo= new FifoVideoFrames( m_vfifosize , &m_video_format); } } else { m_video_stream_count = 0; m_veof = true; } // we use the m_afifosize to see if the user app wants audio or not // then, we set m_audio_stream_count to 0 if he doesn't want audio if (m_audio_stream_count > 0 && m_afifosize > 0) { open_audio_format = bgav_get_audio_format(m_file, 0); // we can get audio formats that are unkown if ( open_audio_format->sample_format == GAVL_SAMPLE_NONE) { printf("sorry, this file has unsupported audio.\n"); return false; } if ( gavl_audio_formats_equal(&m_audio_format, open_audio_format) == 0 ) { // audio formats are different // save the old spf int spf = m_audio_format.samples_per_frame; gavl_audio_format_copy(&m_audio_format, open_audio_format); if (m_audio_frame != NULL) { gavl_audio_frame_destroy(m_audio_frame); } // set it back to original m_audio_format.samples_per_frame = spf ; m_audio_frame = gavl_audio_frame_create(&m_audio_format); gavl_audio_frame_mute( m_audio_frame, &m_audio_format); if( m_fifoaudio != NULL ) delete m_fifoaudio; m_fifoaudio = new FifoAudioFrames( m_afifosize , &m_audio_format); } } else { // user doesn't want audio m_audio_stream_count = 0; m_aeof=true; } m_length_in_gavltime = bgav_get_duration ( m_file, 0);; m_length_in_seconds = gavl_time_to_seconds( m_length_in_gavltime ); m_num_samples = 0; m_num_frames = 0; if (m_audio_stream_count) { if ( bgav_can_seek_sample(m_file) == 1 ) { m_num_samples= bgav_audio_duration ( m_file, 0) ; } else { m_num_samples= gavl_time_to_samples( m_audio_format.samplerate , bgav_get_duration ( m_file, 0) ); } } // set frames WE NEED TO take care here for non-constant frame-rates if(m_video_stream_count) { if ( bgav_can_seek_sample(m_file) == 1 && m_video_format.framerate_mode == GAVL_FRAMERATE_CONSTANT) { m_num_frames = bgav_video_duration ( m_file, 0)/ m_video_format.frame_duration; } else if ( bgav_can_seek_sample(m_file) == 1 && m_video_format.framerate_mode == GAVL_FRAMERATE_VARIABLE ) { // FIXME what to do with non constant frame rates? m_num_frames=0; } else { m_num_frames = gavl_time_to_frames( m_video_format.timescale, m_video_format.frame_duration , bgav_get_duration ( m_file, 0) ); } } // printf("m_num_frames =%lld, duration = %lld , vid_duration=%lld\n", // m_num_frames, bgav_get_duration ( m_file, 0), bgav_video_duration ( m_file, 0) ); // set seconds if ( bgav_can_seek_sample(m_file) == 1) { gavl_time_t atime=0,vtime=0; if ( m_audio_stream_count ) atime = gavl_samples_to_time( m_audio_format.samplerate, m_num_samples ); if (m_video_stream_count && m_video_format.frame_duration > 0) { vtime = gavl_frames_to_time( m_video_format.timescale, m_video_format.frame_duration, m_num_frames ); } else if ( m_video_stream_count ) { // non constant framerate vtime = bgav_video_duration( m_file, 0); } // else rely on audio time m_length_in_gavltime = atime > vtime ? atime :vtime; m_length_in_seconds = gavl_time_to_seconds( m_length_in_gavltime ); //printf("atime=%ld, vtime=%ld, l_in_sec=%f\n", atime, vtime, m_length_in_seconds); } m_pcm_seek = SEEK_NOTHING; m_frame_seek = SEEK_NOTHING; return true; }