ssize_t fs_queue_read(struct fs_queue * fsq, uint8_t * buf, size_t count, int flags) { ssize_t rd = 0; size_t offset, bytes = 0, left = count; /* * Freeze last_wr_packet because we might be reading it next, * thus it's not ok to modify it anymore. */ mtx_lock(&fsq->wr_lock); fsq->last_wr_packet = NULL; fsq->last_wr = 0; mtx_unlock(&fsq->wr_lock); mtx_lock(&fsq->rd_lock); offset = fsq->last_rd; if (flags & FS_QUEUE_FLAGS_PACKET && count == 0) { queue_skip(&fsq->qcb, 1); goto out; } while (left > 0) { struct fs_queue_packet * p; if ((flags & FS_QUEUE_FLAGS_NONBLOCK) && !queue_peek(&fsq->qcb, (void **)(&p))) { goto out; } else { /* Blocking IO */ sigset_t oldset; fsq_sigwait_init(fsq, FSQ_WAIT4WRITE, &oldset); while (!queue_peek(&fsq->qcb, (void **)(&p))) { /* * Queue is empty. * Wait for the writing end to write something. */ fsq_sigwait(); } /* Reset sigmask and wait state. */ fsq_sigwait_clear(fsq, FSQ_WAIT4WRITE, &oldset); } bytes = min(left, p->size - offset); memmove(buf + rd, p->data + offset, bytes); left -= bytes; rd += bytes; if (flags & FS_QUEUE_FLAGS_PACKET) { queue_skip(&fsq->qcb, 1); bytes = 0; break; } else if (offset + bytes >= p->size) { queue_skip(&fsq->qcb, 1); bytes = 0; offset = 0; } } fsq->last_rd = bytes; out: fsq_sigsend(fsq, FSQ_WAIT4READ); mtx_unlock(&fsq->rd_lock); return rd; }
int main(int argc, char *argv[]){ printf("Preparing...\n"); //Sound preparing wav_get_info(SOUND,&info); sound_dev_prepare(DEVICE, &(info.dev), info.fmt.sample_rate, info.fmt.channels); queue_init(&s_queue, info.dev.buff_size_bytes); //Done //Some usefull info about wav-file #ifdef WAV_INFO printf("File Name: %s\n Chunk ID: %s\n Data Size: %u\n RIFF type: %s\n Chunk ID: %s\n Fmt Data Size: %d\n Comression code: 0x%04x\n Channels: %u\n Sample Rate: %u\n Average Bytes Per Second: %u\n Block Align: %u\n Significant Bytes Per Second: %u\n Chunk ID: %s\n Data Size: %u\n",SOUND,info.riff.id, info.riff.data_size,info.riff.type, info.fmt.id, info.fmt.data_size, info.fmt.compression, info.fmt.channels, info.fmt.sample_rate, info.fmt.av_bps, info.fmt.block_align, info.fmt.sign_bps, info.data.id, info.data.size); #endif //Let's play some music! struct reader_t reader_info; int time; if (argc == 3){ sscanf(argv[1],"%u",&reader_info.start_sound); sscanf(argv[2],"%u",&time); } else { reader_info.start_sound = 0; time = 1; } reader_info.start_frame = (reader_info.start_sound * FPS) / 1000; reader_info.sound_offset = info.data.offset; reader_info.sound_buff_size = info.dev.buff_size_bytes; pthread_create(&r_th, NULL, reader, &(reader_info)); struct timeval time1; struct timezone tz; int fps_timeout = 1000000000 / FPS; memset(&tz, 0, sizeof(tz)); struct timespec timeout; timeout.tv_sec = 0; timeout.tv_nsec = 0; struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; while(buffer_ready == FALSE) wait(&tv); struct packet_t *s_buff, *v_buff; sound_buff = (*(queue_pop(&s_queue))).data; s_buff = queue_pop_next(&s_queue); video_buff = (*(queue_pop(&v_queue))).data; v_buff = queue_pop_next(&s_queue); pthread_create(&s_th, NULL, sound_thread, &(info.dev)); pthread_create(&v_th, NULL, video_thread, NULL); printf("Threads started...\n"); while(v_ready == FALSE) wait(&tv); //----------------------* KICKER int frames = 0; int rc = 0; printf("Ready to play...\n"); int no_skip = 0; for(int i = 0; i < ((time * FPS )/ 1000); ++i){ pthread_cond_signal(&s_cond); pthread_cond_signal(&v_cond); v_buff = queue_pop_next(&v_queue); gettimeofday(&time1, &tz); pthread_mutex_lock(&k_mutex); timeout.tv_nsec = fps_timeout*1000; add_timespec(&timeout, &time1); rc = pthread_cond_timedwait(&k_cond, &k_mutex, (const struct timespec *restrict)&timeout); pthread_mutex_unlock(&k_mutex); if (rc == 0){ sound_buff = (*s_buff).data; pthread_cond_signal(&s_cond); queue_skip(&s_queue,1); frames = (s_buff->timestamp / 1000) - (v_buff->timestamp / 1000); printf("DEBUG: S: %ld V: %ld\n",s_buff->timestamp / 1000,v_buff->timestamp / 1000); if (frames > 0){ queue_skip(&v_queue,frames); printf("DEBUG: Skip frames: %d\n",frames); } else if (frames < 0) { printf("DEBUG: No skip: %d\n",-frames); no_skip = -frames; } s_buff = queue_pop_next(&s_queue); } video_buff = (*v_buff).data; if (no_skip > 0){ --no_skip; } else { queue_skip(&v_queue,1); } } pthread_cond_signal(&s_cond); printf("THE END\n"); //---------------------------* KICKER END termination(); return 0; }