static void finalize (GObject *object) { GeglProperties *o = GEGL_PROPERTIES (object); if (o->user_data) { Priv *p = (Priv*)o->user_data; flush_audio (o); flush_video (o); av_write_trailer (p->oc); if (p->video_st) close_video (p, p->oc, p->video_st); if (p->audio_st) close_audio (p, p->oc, p->audio_st); avio_closep (&p->oc->pb); avformat_free_context (p->oc); g_free (o->user_data); o->user_data = NULL; } G_OBJECT_CLASS (g_type_class_peek_parent (G_OBJECT_GET_CLASS (object)))->finalize (object); }
// close audio device static void uninit(int immed){ // throw away buffered data in the audio driver's STREAMS queue if (immed) flush_audio(audio_fd); else ioctl(audio_fd, AUDIO_DRAIN, 0); close(audio_fd); }
// stop playing and empty buffers (for seeking/pause) static void reset(void){ audio_info_t info; flush_audio(audio_fd); AUDIO_INITINFO(&info); info.play.samples = 0; info.play.eof = 0; info.play.error = 0; ioctl(audio_fd, AUDIO_SETINFO, &info); queued_bursts = 0; queued_samples = 0; }
// try to figure out, if the soundcard driver provides usable (precise) // sample counter information static int realtime_samplecounter_available(char *dev) { int fd = -1; audio_info_t info; int rtsc_ok = RTSC_DISABLED; int len; void *silence = NULL; struct timeval start, end; struct timespec delay; int usec_delay; unsigned last_samplecnt; unsigned increment; unsigned min_increment; len = 44100 * 4 / 4; /* amount of data for 0.25sec of 44.1khz, stereo, * 16bit. 44kbyte can be sent to all supported * sun audio devices without blocking in the * "write" below. */ silence = calloc(1, len); if (silence == NULL) goto error; if ((fd = open(dev, O_WRONLY)) < 0) goto error; AUDIO_INITINFO(&info); info.play.sample_rate = 44100; info.play.channels = AUDIO_CHANNELS_STEREO; info.play.precision = AUDIO_PRECISION_16; info.play.encoding = AUDIO_ENCODING_LINEAR; info.play.samples = 0; if (ioctl(fd, AUDIO_SETINFO, &info)) { if ( mp_msg_test(MSGT_AO,MSGL_V) ) mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SUN_RtscSetinfoFailed); goto error; } if (write(fd, silence, len) != len) { if ( mp_msg_test(MSGT_AO,MSGL_V) ) mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SUN_RtscWriteFailed); goto error; } if (ioctl(fd, AUDIO_GETINFO, &info)) { if ( mp_msg_test(MSGT_AO,MSGL_V) ) perror("rtsc: GETINFO1"); goto error; } last_samplecnt = info.play.samples; min_increment = ~0; gettimeofday(&start, NULL); for (;;) { delay.tv_sec = 0; delay.tv_nsec = 10000000; nanosleep(&delay, NULL); gettimeofday(&end, NULL); usec_delay = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec; // stop monitoring sample counter after 0.2 seconds if (usec_delay > 200000) break; if (ioctl(fd, AUDIO_GETINFO, &info)) { if ( mp_msg_test(MSGT_AO,MSGL_V) ) perror("rtsc: GETINFO2 failed"); goto error; } if (info.play.samples < last_samplecnt) { if ( mp_msg_test(MSGT_AO,MSGL_V) ) mp_msg(MSGT_AO,MSGL_V,"rtsc: %d > %d?\n", last_samplecnt, info.play.samples); goto error; } if ((increment = info.play.samples - last_samplecnt) > 0) { if ( mp_msg_test(MSGT_AO,MSGL_V) ) mp_msg(MSGT_AO,MSGL_V,"ao_sun: sample counter increment: %d\n", increment); if (increment < min_increment) { min_increment = increment; if (min_increment < 2000) break; // looks good } } last_samplecnt = info.play.samples; } /* * For 44.1kkz, stereo, 16-bit format we would send sound data in 16kbytes * chunks (== 4096 samples) to the audio device. If we see a minimum * sample counter increment from the soundcard driver of less than * 2000 samples, we assume that the driver provides a useable realtime * sample counter in the AUDIO_INFO play.samples field. Timing based * on sample counts should be much more accurate than counting whole * 16kbyte chunks. */ if (min_increment < 2000) rtsc_ok = RTSC_ENABLED; if ( mp_msg_test(MSGT_AO,MSGL_V) ) mp_msg(MSGT_AO,MSGL_V,"ao_sun: minimum sample counter increment per 10msec interval: %d\n" "\t%susing sample counter based timing code\n", min_increment, rtsc_ok == RTSC_ENABLED ? "" : "not "); error: if (silence != NULL) free(silence); if (fd >= 0) { // remove the 0 bytes from the above measurement from the // audio driver's STREAMS queue flush_audio(fd); close(fd); } return rtsc_ok; }