From 21a0bd773519c5bd39a5293f2e66ea59add8d0a9 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 11 Mar 2007 17:34:00 +0100 Subject: [PATCH] introduce struct audio_format_info This further simplifies the audio format handlers. The chunk_table and the header info is now contained in that struct which allows to move the cleanup on eof from the audio format handlers to the virtual streaming system. --- aac_afh.c | 41 ++++++++++++--------------- afh.h | 69 ++++++++++++++++++++++++++------------------ command.c | 32 ++++++++++----------- mp3_afh.c | 50 ++++++++++++++------------------ ogg_afh.c | 85 ++++++++++++++++++++++--------------------------------- server.c | 1 + server.h | 10 ++----- vss.c | 39 ++++++++++++------------- 8 files changed, 155 insertions(+), 172 deletions(-) diff --git a/aac_afh.c b/aac_afh.c index 956ff6da..5e5ea965 100644 --- a/aac_afh.c +++ b/aac_afh.c @@ -25,7 +25,6 @@ #include "server.cmdline.h" #include "server.h" #include "vss.h" -#include "afh.h" #include "error.h" #include "string.h" #include "aac.h" @@ -37,7 +36,7 @@ static struct audio_format_handler *af; static FILE *infile; static unsigned char *inbuf; -static size_t inbuf_size, inbuf_len, *chunk_table, num_chunks; +static size_t inbuf_size, inbuf_len, num_chunks; static void aac_close_audio_file(void) { @@ -47,8 +46,6 @@ static void aac_close_audio_file(void) infile = NULL; free(inbuf); inbuf = NULL; - free(chunk_table); - chunk_table = NULL; } static int aac_find_stsz(unsigned char *buf, unsigned buflen, size_t *skip) @@ -76,7 +73,7 @@ static int aac_find_stsz(unsigned char *buf, unsigned buflen, size_t *skip) return -E_STSZ; } -static int read_chunk_table(size_t skip) +static int read_chunk_table(struct audio_format_info *afi, size_t skip) { int ret, i; size_t sum = 0; @@ -92,7 +89,7 @@ static int read_chunk_table(size_t skip) } num_chunks = ret; PARA_INFO_LOG("sz table has %zu entries\n", num_chunks); - chunk_table = para_malloc((num_chunks + 1) * sizeof(size_t)); + afi->chunk_table = para_malloc((num_chunks + 1) * sizeof(size_t)); for (i = 1; i <= num_chunks; i++) { if (skip + 4 > inbuf_len) { skip = inbuf_len - skip; @@ -105,33 +102,33 @@ static int read_chunk_table(size_t skip) PARA_INFO_LOG("next buffer: %zu bytes\n", inbuf_len); } sum += aac_read_int32(inbuf + skip); - chunk_table[i] = sum; + afi->chunk_table[i] = sum; skip += 4; if (i < 10 || i + 10 > num_chunks) - PARA_DEBUG_LOG("offset #%d: %zu\n", i, chunk_table[i]); + PARA_DEBUG_LOG("offset #%d: %zu\n", i, afi->chunk_table[i]); } return 1; } -static long unsigned aac_set_chunk_tv(mp4AudioSpecificConfig *mp4ASC) +static long unsigned aac_set_chunk_tv(struct audio_format_info *afi, + mp4AudioSpecificConfig *mp4ASC) { float tmp = mp4ASC->sbr_present_flag == 1? 2047 : 1023, ms = 1000.0 * num_chunks * tmp / mp4ASC->samplingFrequency; struct timeval total; ms2tv(ms, &total); - tv_divide(num_chunks, &total, &af->chunk_tv); + tv_divide(num_chunks, &total, &afi->chunk_tv); PARA_INFO_LOG("%luHz, %fs (%zd x %lums)\n", mp4ASC->samplingFrequency, ms / 1000, - num_chunks, tv2ms(&af->chunk_tv)); + num_chunks, tv2ms(&afi->chunk_tv)); return ms / 1000; } /* * Init m4a file and write some tech data to given pointers. */ -static int aac_get_file_info(FILE *file, char *info_str, long unsigned *frames, - int *seconds, size_t **vss_chunk_table) +static int aac_get_file_info(FILE *file, struct audio_format_info *afi) { int i, ret, decoder_len; size_t skip; @@ -163,12 +160,11 @@ static int aac_get_file_info(FILE *file, char *info_str, long unsigned *frames, &mp4ASC); if (ret < 0) return -E_MP4ASC; - ret = read_chunk_table(skip); + ret = read_chunk_table(afi, skip); if (ret < 0) return ret; - *frames = num_chunks; - *seconds = aac_set_chunk_tv(&mp4ASC); - *vss_chunk_table = chunk_table; + afi->chunks_total = num_chunks; + afi->seconds_total = aac_set_chunk_tv(afi, &mp4ASC); for (;;) { ret = aac_find_entry_point(inbuf, inbuf_len, &skip); if (ret >= 0) @@ -178,15 +174,15 @@ static int aac_get_file_info(FILE *file, char *info_str, long unsigned *frames, return -E_AAC_READ; PARA_INFO_LOG("next buffer: %d bytes\n", ret); } - chunk_table[0] = ret; + afi->chunk_table[0] = ret; for (i = 1; i<= num_chunks; i++) - chunk_table[i] += ret; - sprintf(info_str, "audio_file_info1:%zu x %lums\n" + afi->chunk_table[i] += ret; + sprintf(afi->info_string, "audio_file_info1:%zu x %lums\n" "audio_file_info2:\n" "audio_file_info3:\n", num_chunks, - tv2ms(&af->chunk_tv)); - tv_scale(20, &af->chunk_tv, &af->eof_tv); + tv2ms(&afi->chunk_tv)); + tv_scale(20, &afi->chunk_tv, &afi->eof_tv); return 1; } @@ -197,6 +193,5 @@ void aac_afh_init(struct audio_format_handler *p) af = p; af->get_file_info = aac_get_file_info, af->close_audio_file = aac_close_audio_file; - af->get_header_info = NULL; af->suffixes = aac_suffixes; } diff --git a/afh.h b/afh.h index 77874108..e7ca2820 100644 --- a/afh.h +++ b/afh.h @@ -41,6 +41,39 @@ /** \endcond */ +/** size of the audio_file info string */ +#define AUDIO_FILE_INFO_SIZE 16384 + +struct audio_format_info { + /** the number of chunks this audio file contains */ + long unsigned chunks_total; + /** the length of the audio file in seconds */ + int seconds_total; + /** a string that gets filled in by the audio format handler */ + char info_string[AUDIO_FILE_INFO_SIZE]; + /** + * the table that specifies the offset of the individual pieces in + * the current audio file. + */ + size_t *chunk_table; + /** period of time between sending data chunks */ + struct timeval chunk_tv; + /** end of file timeout - do not load new audio file until this time */ + struct timeval eof_tv; + /** + * optional audio file header + * + * This is read from a sender in case a new client connects in the + * middle of the stream. The audio format handler does not need to set + * this if the audio format does not need any special header treatment. + * If non-NULL, it must point to a buffer holding the current audio + * file header. + */ + char *header; + /* the length of the header, ignored if \a header is \p NULL */ + unsigned header_len; +}; + /** * structure for audio format handling * @@ -64,37 +97,18 @@ struct audio_format_handler { * Must initialize all function pointers and is assumed to succeed. */ void (*init)(struct audio_format_handler*); - /** - * period of time between sending data chunks - */ - struct timeval chunk_tv; /* length of one chunk of data */ - /** - * end of file timeout - do not load new audio file until this time - * - */ - struct timeval eof_tv; /* timeout on eof */ - /** - * Pointer to the optional get-header function. - * - * This is called from a sender in case a new client connects in the middle of - * the stream. The audio format handler may set this to NULL to indicate that - * this audio format does not need any special header treatment. If non-NULL, - * the function it points to must return a pointer to a buffer holding the - * current audio file header, together with the header length. - */ - char *(*get_header_info)(int *header_len); /** * check if this audio format handler can handle the file * - * This is a pointer to a function returning whether a given file is valid for - * this audio format. A negative return value indicates that this audio format - * handler did not recognize the given file. On success, the function is - * expected to return a positive value and to fill in \arg info_str, \arg - * chunks and \arg seconds appropriately and to return the chunk table - * via \a vss_chunk_table. + * This is a pointer to a function returning whether a given file is + * valid for this audio format. A negative return value indicates that + * this audio format handler did not recognize the given file. On + * success, the function must return a positive value and fill in the + * given struct audio_format_info. + * + * \sa struct audio_format_info */ - int (*get_file_info)(FILE *audio_file, char *info_str, - long unsigned *chunks, int *seconds, size_t **vss_chunk_table); + int (*get_file_info)(FILE *audio_file, struct audio_format_info *afi); /** * cleanup function of this audio format handler * @@ -104,3 +118,4 @@ struct audio_format_handler { */ void (*close_audio_file)(void); }; + diff --git a/command.c b/command.c index 77d3ef7f..2fac5ccf 100644 --- a/command.c +++ b/command.c @@ -114,14 +114,14 @@ static char *get_sb_string(struct misc_meta_data *nmmd) return para_strdup(""); if (!base[0]) return base; - if (nmmd->chunks_total) { - secs = (long long) nmmd->seconds_total * nmmd->chunks_sent - / nmmd->chunks_total; - rsecs = (long long) nmmd->seconds_total * - (nmmd->chunks_total - nmmd->chunks_sent) - / nmmd->chunks_total; + if (nmmd->afi.chunks_total) { + secs = (long long) nmmd->afi.seconds_total * nmmd->chunks_sent + / nmmd->afi.chunks_total; + rsecs = (long long) nmmd->afi.seconds_total * + (nmmd->afi.chunks_total - nmmd->chunks_sent) + / nmmd->afi.chunks_total; percent = 100 * ((nmmd->chunks_sent + 5) / 10) - / ((nmmd->chunks_total + 5) / 10); + / ((nmmd->afi.chunks_total + 5) / 10); } ret = make_message("%llu:%02llu [%llu:%02llu] (%llu%%) %s", secs / 60, secs % 60, @@ -158,7 +158,7 @@ static char *get_status(struct misc_meta_data *nmmd) "%s:%s\n" "%s:%lu.%lu\n" "%s:%lu.%lu\n", status_item_list[SI_FILE_SIZE], nmmd->size / 1024, status_item_list[SI_MTIME], mtime, - status_item_list[SI_LENGTH], nmmd->seconds_total, + status_item_list[SI_LENGTH], nmmd->afi.seconds_total, status_item_list[SI_NUM_PLAYED], nmmd->num_played, status_item_list[SI_STATUS_BAR], bar ? bar : "(none)", @@ -169,7 +169,7 @@ static char *get_status(struct misc_meta_data *nmmd) status_item_list[SI_OFFSET], offset, status_item_list[SI_FORMAT], audio_format_name(nmmd->audio_format), nmmd->selector_info, - nmmd->audio_file_info, + nmmd->afi.info_string, status_item_list[SI_UPTIME], ut, status_item_list[SI_STREAM_START], @@ -649,20 +649,20 @@ int com_ff(__a_unused int fd, int argc, char **argv) backwards = 1; /* jmp backwards */ mmd_lock(); ret = -E_NO_AUDIO_FILE; - if (!mmd->chunks_total || !mmd->seconds_total) + if (!mmd->afi.chunks_total || !mmd->afi.seconds_total) goto out; - promille = (1000 * mmd->current_chunk) / mmd->chunks_total; + promille = (1000 * mmd->current_chunk) / mmd->afi.chunks_total; if (backwards) - promille -= 1000 * i / mmd->seconds_total; + promille -= 1000 * i / mmd->afi.seconds_total; else - promille += 1000 * i / mmd->seconds_total; + promille += 1000 * i / mmd->afi.seconds_total; if (promille < 0) promille = 0; if (promille > 1000) { mmd->new_vss_status_flags |= VSS_NEXT; goto out; } - mmd->repos_request = (mmd->chunks_total * promille) / 1000; + mmd->repos_request = (mmd->afi.chunks_total * promille) / 1000; mmd->new_vss_status_flags |= VSS_REPOS; mmd->new_vss_status_flags &= ~VSS_NEXT; mmd->events++; @@ -684,12 +684,12 @@ int com_jmp(__a_unused int fd, int argc, char **argv) return -E_COMMAND_SYNTAX; mmd_lock(); ret = -E_NO_AUDIO_FILE; - if (!mmd->chunks_total) + if (!mmd->afi.chunks_total) goto out; if (i > 100) i = 100; PARA_INFO_LOG("jumping to %lu%%\n", i); - mmd->repos_request = (mmd->chunks_total * i + 50)/ 100; + mmd->repos_request = (mmd->afi.chunks_total * i + 50)/ 100; PARA_INFO_LOG("sent: %lu, offset before jmp: %lu\n", mmd->chunks_sent, mmd->offset); mmd->new_vss_status_flags |= VSS_REPOS; diff --git a/mp3_afh.c b/mp3_afh.c index 71461248..898547fc 100644 --- a/mp3_afh.c +++ b/mp3_afh.c @@ -31,7 +31,6 @@ #include "server.cmdline.h" #include "server.h" #include "vss.h" -#include "afh.h" #include "error.h" #include "fd.h" #include "string.h" @@ -106,7 +105,7 @@ static const char *mode_text[] = {"stereo", "joint stereo", "dual channel", "mon static FILE *infile; static struct mp3info mp3; static struct audio_format_handler *af; -static ssize_t *chunk_table, num_chunks; +static ssize_t num_chunks; static int header_frequency(struct mp3header *h) { @@ -144,16 +143,16 @@ static int frame_length(struct mp3header *header) + header->padding; } -static void write_info_str(char *info_str) +static void write_info_str(struct audio_format_info *afi) { int v = mp3.id3_isvalid; - snprintf(info_str, MMD_INFO_SIZE, + snprintf(afi->info_string, MMD_INFO_SIZE, "audio_file_info1:%d x %lums, %lu kbit/s (%cbr) %i KHz %s\n" "audio_file_info2:%s, by %s\n" "audio_file_info3:A: %s, Y: %s, C: %s\n", num_chunks, - tv2ms(&af->chunk_tv), + tv2ms(&afi->chunk_tv), mp3.br_average, mp3.vbr? 'v' : 'c', mp3.freq / 1000, @@ -354,7 +353,7 @@ static int find_valid_start(void) return frame_len; } -static int mp3_read_info(void) +static int mp3_read_info(struct audio_format_info *afi) { long fl_avg = 0, freq_avg = 0, br_avg = 0; int ret, len = 0, old_br = -1; @@ -362,7 +361,7 @@ static int mp3_read_info(void) unsigned chunk_table_size = 1000; /* gets increased on demand */ num_chunks = 0; - chunk_table = para_malloc(chunk_table_size * sizeof(size_t)); + afi->chunk_table = para_malloc(chunk_table_size * sizeof(size_t)); ret = mp3_get_id3(); if (ret < 0) goto err_out; @@ -393,13 +392,13 @@ static int mp3_read_info(void) //PARA_DEBUG_LOG("%s: br: %d, freq: %d, fl: %d, cct: %lu\n", __func__, br, freq, fl, cct.tv_usec); if (num_chunks >= chunk_table_size) { chunk_table_size *= 2; - chunk_table = para_realloc(chunk_table, + afi->chunk_table = para_realloc(afi->chunk_table, chunk_table_size * sizeof(size_t)); } - chunk_table[num_chunks] = ftell(infile); + afi->chunk_table[num_chunks] = ftell(infile); if (num_chunks < 10 || !(num_chunks % 1000)) PARA_INFO_LOG("chunk #%d: %zd\n", num_chunks, - chunk_table[num_chunks]); + afi->chunk_table[num_chunks]); num_chunks++; if (num_chunks == 1) { // entry = ftell(infile); @@ -423,43 +422,41 @@ static int mp3_read_info(void) ret= para_fseek(infile, 0, SEEK_END); if (ret < 0) goto err_out; - chunk_table[num_chunks] = ftell(infile); + afi->chunk_table[num_chunks] = ftell(infile); mp3.br_average = br_avg; mp3.freq = freq_avg; mp3.seconds = (tv2ms(&total_time) + 500) / 1000; - tv_divide(num_chunks, &total_time, &af->chunk_tv); + tv_divide(num_chunks, &total_time, &afi->chunk_tv); rewind(infile); - PARA_DEBUG_LOG("%zu chunks, each %lums\n", num_chunks, tv2ms(&af->chunk_tv)); - tv_scale(3, &af->chunk_tv, &af->eof_tv); - PARA_DEBUG_LOG("eof timeout: %lu\n", tv2ms(&af->eof_tv)); + PARA_DEBUG_LOG("%zu chunks, each %lums\n", num_chunks, tv2ms(&afi->chunk_tv)); + tv_scale(3, &afi->chunk_tv, &afi->eof_tv); + PARA_DEBUG_LOG("eof timeout: %lu\n", tv2ms(&afi->eof_tv)); return 1; err_out: PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); - free(chunk_table); + free(afi->chunk_table); return ret; } /* * Read mp3 information from audio file */ -static int mp3_get_file_info(FILE *audio_file, char *info_str, - long unsigned *frames, int *seconds, size_t **vss_chunk_table) +static int mp3_get_file_info(FILE *audio_file, struct audio_format_info *afi) { int ret; if (!audio_file) return -E_MP3_NO_FILE; infile = audio_file; - ret = mp3_read_info(); + ret = mp3_read_info(afi); if (ret < 0) { infile = NULL; return ret; } - write_info_str(info_str); - *frames = num_chunks; - *seconds = mp3.seconds; - *vss_chunk_table = chunk_table; - if (*seconds < 2 || !*frames) + write_info_str(afi); + afi->chunks_total = num_chunks; + afi->seconds_total = mp3.seconds; + if (afi->seconds_total < 2 || !afi->chunks_total) return -E_MP3_INFO; return 1; } @@ -470,7 +467,6 @@ static void mp3_close_audio_file(void) return; fclose(infile); infile = NULL; - free(chunk_table); } static const char* mp3_suffixes[] = {"mp3", NULL}; @@ -485,9 +481,5 @@ void mp3_init(struct audio_format_handler *p) af = p; af->get_file_info = mp3_get_file_info; af->close_audio_file = mp3_close_audio_file; - af->get_header_info = NULL; - /* eof_tv gets overwritten in mp3_get_file_info() */ - af->eof_tv.tv_sec = 0; - af->eof_tv.tv_usec = 100 * 1000; af->suffixes = mp3_suffixes; } diff --git a/ogg_afh.c b/ogg_afh.c index dd0a5405..f972c630 100644 --- a/ogg_afh.c +++ b/ogg_afh.c @@ -25,7 +25,6 @@ #include "server.cmdline.h" #include "server.h" #include "vss.h" -#include "afh.h" #include "error.h" #include "string.h" @@ -34,9 +33,6 @@ static double chunk_time = 0.25; FILE *audio_file; -static int header_len; -static char *header; -static ssize_t *chunk_table; static struct audio_format_handler *af; static size_t cb_read(void *buf, size_t size, size_t nmemb, void *datasource) @@ -86,7 +82,20 @@ int ogg_open_callbacks(void *datasource, OggVorbis_File *vf, ov_callbacks c) } -static int ogg_compute_header_len(FILE *file) +static int ogg_save_header(FILE *file, struct audio_format_info *afi) +{ + int ret; + + afi->header = para_malloc(afi->header_len); + rewind(file); + ret = read(fileno(file), afi->header, afi->header_len); + if (ret == afi->header_len) + return 1; + free(afi->header); + return -E_OGG_READ; +} + +static int ogg_compute_header_len(FILE *file, struct audio_format_info *afi) { int ret, len, in = fileno(file); unsigned int serial; @@ -148,11 +157,11 @@ static int ogg_compute_header_len(FILE *file) ogg_stream_packetout(stream_in, &packet); ogg_stream_packetin(stream_out, &packet); - header_len = 0; + afi->header_len = 0; while (ogg_stream_flush(stream_out, &page)) - header_len += page.body_len + page.header_len; - ret = len; - PARA_INFO_LOG("header_len = %d\n", header_len); + afi->header_len += page.body_len + page.header_len; + PARA_INFO_LOG("header_len = %d\n", afi->header_len); + ret = ogg_save_header(file, afi); err2: ogg_stream_destroy(stream_in); ogg_stream_destroy(stream_out); @@ -169,7 +178,7 @@ err1: * CHUNK_TIME begins. Always successful. */ static long unsigned ogg_compute_chunk_table(OggVorbis_File *of, - double time_total) + struct audio_format_info *afi, double time_total) { int i, ret, num; ssize_t max_chunk_len, pos = 0, min = 0, old_pos; @@ -180,8 +189,8 @@ static long unsigned ogg_compute_chunk_table(OggVorbis_File *of, num = time_total / chunk_time + 3; PARA_DEBUG_LOG("chunk time: %g allocating %d chunk pointers\n", chunk_time, num); - chunk_table = para_malloc(num * sizeof(size_t)); - chunk_table[0] = 0; + afi->chunk_table = para_malloc(num * sizeof(size_t)); + afi->chunk_table[0] = 0; max_chunk_len = 0; for (i = 1; ret == 0; i++) { ogg_int64_t diff; @@ -192,7 +201,7 @@ static long unsigned ogg_compute_chunk_table(OggVorbis_File *of, diff = pos - old_pos; max_chunk_len = PARA_MAX(max_chunk_len, diff); min = (i == 1)? diff : PARA_MIN(min, diff); - chunk_table[i] = pos; + afi->chunk_table[i] = pos; if (i < 11 || !((i - 1) % 1000)|| i > num - 11) PARA_DEBUG_LOG("chunk #%d: %g secs, pos: %zd, " "size: %zd\n", i - 1, @@ -200,7 +209,7 @@ static long unsigned ogg_compute_chunk_table(OggVorbis_File *of, old_pos = pos; } num_chunks = i - 1; - chunk_table[i] = pos; + afi->chunk_table[i] = pos; PARA_INFO_LOG("%lu chunks (%fs), max chunk: %zd, min chunk: %zd\n", num_chunks, chunk_time, max_chunk_len, min); return num_chunks; @@ -208,29 +217,13 @@ static long unsigned ogg_compute_chunk_table(OggVorbis_File *of, static void ogg_close_audio_file(void) { - free(header); - free(chunk_table); fclose(audio_file); } -static int ogg_save_header(FILE *file, int len) -{ - int ret; - - header = para_malloc(len); - rewind(file); - ret = read(fileno(file), header, len); - if (ret == len) - return 1; - free(header); - return -E_OGG_READ; -} - /* * Init oggvorbis file and write some tech data to given pointers. */ -static int ogg_get_file_info(FILE *file, char *info_str, long unsigned *frames, - int *seconds, size_t **vss_chunk_table) +static int ogg_get_file_info(FILE *file, struct audio_format_info *afi) { int ret; double time_total; @@ -247,10 +240,7 @@ static int ogg_get_file_info(FILE *file, char *info_str, long unsigned *frames, if (!file) return -E_OGG_NO_FILE; - ret = ogg_compute_header_len(file); - if (ret < 0) - return ret; - ret = ogg_save_header(file, header_len); + ret = ogg_compute_header_len(file, afi); if (ret < 0) return ret; rewind(file); @@ -263,35 +253,32 @@ static int ogg_get_file_info(FILE *file, char *info_str, long unsigned *frames, goto err; time_total = ov_time_total(&of, -1); raw_total = ov_raw_total(&of, -1); - *seconds = time_total; + afi->seconds_total = time_total; vi_sampling_rate = vi->rate; vi_bitrate = ov_bitrate(&of, 0); rewind(file); - *frames = ogg_compute_chunk_table(&of, time_total); + afi->chunks_total = ogg_compute_chunk_table(&of, afi, time_total); rewind(file); - *vss_chunk_table = chunk_table; - sprintf(info_str, "audio_file_info1:%lu x %lu, %ldkHz, %d channels, %ldkbps\n" + sprintf(afi->info_string, "audio_file_info1:%lu x %lu, %ldkHz, " + "%d channels, %ldkbps\n" "audio_file_info2: \n" "audio_file_info3: \n", - *frames, (long unsigned) (chunk_time * 1000 * 1000), + afi->chunks_total, (long unsigned) (chunk_time * 1000 * 1000), vi_sampling_rate / 1000, vi->channels, vi_bitrate / 1000 ); rewind(file); audio_file = file; + afi->chunk_tv.tv_sec = 0; + afi->chunk_tv.tv_usec = 250 * 1000; + tv_scale(3, &afi->chunk_tv, &afi->eof_tv); ret = 1; err: ov_clear(&of); /* keeps the file open */ if (ret < 0) - free(header); + free(afi->header); return ret; } -static char *ogg_get_header_info(int *len) -{ - *len = header_len; - return header; -} - static const char* ogg_suffixes[] = {"ogg", NULL}; /** @@ -304,9 +291,5 @@ void ogg_init(struct audio_format_handler *p) af = p; af->get_file_info = ogg_get_file_info, af->close_audio_file = ogg_close_audio_file; - af->get_header_info = ogg_get_header_info; - af->chunk_tv.tv_sec = 0; - af->chunk_tv.tv_usec = 250 * 1000; - tv_scale(3, &af->chunk_tv, &af->eof_tv); af->suffixes = ogg_suffixes; } diff --git a/server.c b/server.c index 41d9a2ac..7e52fa5e 100644 --- a/server.c +++ b/server.c @@ -369,6 +369,7 @@ static unsigned do_inits(int argc, char **argv) if (conf.daemon_given) daemon_init(); init_selector(); +// PARA_ERROR_LOG("num: %d\n", mmd->selector_num); PARA_NOTICE_LOG("%s", "initializing virtual streaming system\n"); vss_init(); mmd->server_pid = getpid(); diff --git a/server.h b/server.h index 9dee3e34..efee2dbd 100644 --- a/server.h +++ b/server.h @@ -19,6 +19,7 @@ /** \file server.h common server data structures */ #include "para.h" +#include "afh.h" #include /** size of the selector_info and audio_file info strings of struct misc_meta_data */ @@ -72,7 +73,8 @@ struct sender_command_data{ * - The contents are listed in the stat command and have to be up to * date. */ -struct misc_meta_data{ +struct misc_meta_data { + struct audio_format_info afi; /** the size of the current audio file in bytes */ long unsigned int size; /** the full path of the current audio file */ @@ -87,20 +89,14 @@ struct misc_meta_data{ unsigned int new_vss_status_flags; /** the number of data chunks sent for the current audio file */ long unsigned chunks_sent; -/** the number of chunks this audio file contains */ - long unsigned chunks_total; /** set by the jmp/ff commands to the new position in chunks */ long unsigned repos_request; /** the number of the chunk currently sent out*/ long unsigned current_chunk; /** the milliseconds that have been skipped of the current audio file */ long offset; -/** the length of the audio file in seconds */ - int seconds_total; /** the time para_server started to stream */ struct timeval stream_start; -/** a string that gets filled in by the audio format handler */ - char audio_file_info[MMD_INFO_SIZE]; /** the event counter * * commands may increase this to force a status update to be sent to all diff --git a/vss.c b/vss.c index 9aeff44f..d0b21da2 100644 --- a/vss.c +++ b/vss.c @@ -26,7 +26,6 @@ #include /* gettimeofday */ #include "server.cmdline.h" #include "afs.h" -#include "afh.h" #include "vss.h" #include "send.h" #include "error.h" @@ -44,7 +43,7 @@ extern struct misc_meta_data *mmd; extern struct audio_file_selector selectors[]; extern struct sender senders[]; static char *inbuf; -static size_t *chunk_table, inbuf_size; +static size_t inbuf_size; static FILE *audio_file = NULL; @@ -186,8 +185,7 @@ void vss_init(void) static int get_file_info(int i) { - return afl[i].get_file_info(audio_file, mmd->audio_file_info, - &mmd->chunks_total, &mmd->seconds_total, &chunk_table); + return afl[i].get_file_info(audio_file, &mmd->afi); } /** @@ -321,7 +319,7 @@ static void vss_next_chunk_time(struct timeval *due) { struct timeval tmp; - tv_scale(mmd->chunks_sent, &afl[mmd->audio_format].chunk_tv, &tmp); + tv_scale(mmd->chunks_sent, &mmd->afi.chunk_tv, &tmp); tv_add(&tmp, &mmd->stream_start, due); } @@ -373,17 +371,22 @@ static void vss_eof(struct audio_format_handler *af) return; } gettimeofday(&now, NULL); - tv_add(&af->eof_tv, &now, &eof_barrier); + tv_add(&mmd->afi.eof_tv, &now, &eof_barrier); af->close_audio_file(); audio_file = NULL; mmd->audio_format = -1; af = NULL; mmd->chunks_sent = 0; mmd->offset = 0; - mmd->seconds_total = 0; + mmd->afi.seconds_total = 0; + free(mmd->afi.chunk_table); + mmd->afi.chunk_table = NULL; + PARA_ERROR_LOG("freeing header %p\n", mmd->afi.header); + free(mmd->afi.header); + mmd->afi.header = NULL; tmp = make_message("%s:\n%s:\n%s:\n", status_item_list[SI_AUDIO_INFO1], status_item_list[SI_AUDIO_INFO2], status_item_list[SI_AUDIO_INFO3]); - strcpy(mmd->audio_file_info, tmp); + strcpy(mmd->afi.info_string, tmp); free(tmp); tmp = make_message("%s:\n%s:\n%s:\n", status_item_list[SI_DBINFO1], status_item_list[SI_DBINFO2], status_item_list[SI_DBINFO3]); @@ -406,12 +409,10 @@ static void vss_eof(struct audio_format_handler *af) */ char *vss_get_header(int *header_len) { - *header_len = 0; if (mmd->audio_format < 0) return NULL; - if (!afl[mmd->audio_format].get_header_info) - return NULL; - return afl[mmd->audio_format].get_header_info(header_len); + *header_len = mmd->afi.header_len; + return mmd->afi.header; } /** @@ -436,7 +437,7 @@ struct timeval *vss_chunk_time(void) { if (mmd->audio_format < 0) return NULL; - return &afl[mmd->audio_format].chunk_tv; + return &mmd->afi.chunk_tv; } /** @@ -479,7 +480,7 @@ again: struct timeval now; gettimeofday(&now, NULL); if (!vss_paused() || mmd->chunks_sent) - tv_add(&af->eof_tv, &now, &eof_barrier); + tv_add(&mmd->afi.eof_tv, &now, &eof_barrier); if (vss_repos()) tv_add(&now, &announce_tv, &data_send_barrier); if (mmd->new_vss_status_flags & VSS_NOMORE) @@ -517,15 +518,15 @@ ssize_t vss_read_chunk(void) int ret; long unsigned cc = mmd->current_chunk; - if (cc >= mmd->chunks_total) /* eof */ + if (cc >= mmd->afi.chunks_total) /* eof */ return 0; - len = chunk_table[cc + 1] - chunk_table[cc]; + len = mmd->afi.chunk_table[cc + 1] - mmd->afi.chunk_table[cc]; if (!len) /* nothing to send for this run */ return -E_EMPTY_CHUNK; - pos = chunk_table[cc]; + pos = mmd->afi.chunk_table[cc]; if (inbuf_size < len) { PARA_INFO_LOG("increasing inbuf for chunk #%lu/%lu to %zu bytes\n", - cc, mmd->chunks_total, len); + cc, mmd->afi.chunks_total, len); inbuf = para_realloc(inbuf, len); inbuf_size = len; } @@ -586,7 +587,7 @@ void vss_send_chunk(void) if (!mmd->chunks_sent) { struct timeval tmp; gettimeofday(&mmd->stream_start, NULL); - tv_scale(mmd->current_chunk, &af->chunk_tv, &tmp); + tv_scale(mmd->current_chunk, &mmd->afi.chunk_tv, &tmp); mmd->offset = tv2ms(&tmp); mmd->events++; } -- 2.39.2