summaryrefslogtreecommitdiff
path: root/src/demuxers/demux_roq.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/demuxers/demux_roq.c')
-rw-r--r--src/demuxers/demux_roq.c217
1 files changed, 116 insertions, 101 deletions
diff --git a/src/demuxers/demux_roq.c b/src/demuxers/demux_roq.c
index 5e90198c6..c0904acc2 100644
--- a/src/demuxers/demux_roq.c
+++ b/src/demuxers/demux_roq.c
@@ -21,7 +21,7 @@
* For more information regarding the RoQ file format, visit:
* http://www.csse.monash.edu.au/~timf/
*
- * $Id: demux_roq.c,v 1.14 2002/09/10 15:07:14 mroi Exp $
+ * $Id: demux_roq.c,v 1.15 2002/09/21 19:47:11 tmmm Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -124,7 +124,6 @@ static void *demux_roq_loop (void *this_gen) {
/* adjust the chunk size */
chunk_size += RoQ_CHUNK_PREAMBLE_SIZE;
-
if( this->audio_fifo ) {
/* do this calculation carefully because I can't trust the
@@ -158,7 +157,6 @@ static void *demux_roq_loop (void *this_gen) {
if (!chunk_size)
buf->decoder_flags |= BUF_FLAG_FRAME_END;
this->audio_fifo->put(this->audio_fifo, buf);
-//printf ("audio packet pts = %lld\n", buf->pts);
}
} else {
/* no audio -> skip chunk */
@@ -191,7 +189,6 @@ static void *demux_roq_loop (void *this_gen) {
}
/* packetize the video chunk and route it to the video fifo */
-//printf ("total video chunk size = %X\n", chunk_size);
while (chunk_size) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_VIDEO_ROQ;
@@ -213,8 +210,6 @@ static void *demux_roq_loop (void *this_gen) {
if (!chunk_size)
buf->decoder_flags |= BUF_FLAG_FRAME_END;
this->video_fifo->put(this->video_fifo, buf);
-//printf ("loaded video packet with %X bytes, pts = %lld\n",
-// buf->size, buf->pts);
}
video_pts_counter += this->frame_pts_inc;
} else {
@@ -250,6 +245,113 @@ static void *demux_roq_loop (void *this_gen) {
return NULL;
}
+static int load_roq_and_send_headers(demux_roq_t *this) {
+
+ char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
+ int i;
+ unsigned int chunk_type;
+ unsigned int chunk_size;
+
+ pthread_mutex_lock(&this->mutex);
+
+ this->video_fifo = this->xine->video_fifo;
+ this->audio_fifo = this->xine->audio_fifo;
+
+ this->status = DEMUX_OK;
+
+ this->input->seek(this->input, 0, SEEK_SET);
+ if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
+ RoQ_CHUNK_PREAMBLE_SIZE) {
+ this->status = DEMUX_FINISHED;
+ pthread_mutex_unlock(&this->mutex);
+ return DEMUX_CANNOT_HANDLE;
+ }
+
+ this->width = this->height = 0;
+ this->audio_channels = 0; /* assume no audio at first */
+
+ /*
+ * RoQ files enjoy a constant framerate; pts calculation:
+ *
+ * xine pts frame #
+ * -------- = ------- => xine pts = 90000 * frame # / fps
+ * 90000 fps
+ *
+ * therefore, the frame pts increment is 90000 / fps
+ */
+ this->fps = LE_16(&preamble[6]);
+ this->frame_pts_inc = 90000 / this->fps;
+
+ /* iterate through the first 2 seconds worth of chunks searching for
+ * the RoQ_INFO chunk and an audio chunk */
+ i = this->fps * 2;
+ while (i-- > 0) {
+ /* if this read fails, then maybe it's just a really small RoQ file
+ * (even less than 2 seconds) */
+ if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
+ RoQ_CHUNK_PREAMBLE_SIZE)
+ break;
+ chunk_type = LE_16(&preamble[0]);
+ chunk_size = LE_32(&preamble[2]);
+
+ if (chunk_type == RoQ_INFO) {
+ /* fetch the width and height; reuse the preamble bytes */
+ if (this->input->read(this->input, preamble, 8) != 8)
+ break;
+
+ this->width = LE_16(&preamble[0]);
+ this->height = LE_16(&preamble[2]);
+
+ /* if an audio chunk was already found, search is done */
+ if (this->audio_channels)
+ break;
+
+ /* prep the size for a seek */
+ chunk_size -= 8;
+ } else {
+ /* if it was an audio chunk and the info chunk has already been
+ * found (as indicated by width and height) then break */
+ if (chunk_type == RoQ_SOUND_MONO) {
+ this->audio_channels = 1;
+ if (this->width && this->height)
+ break;
+ } else if (chunk_type == RoQ_SOUND_STEREO) {
+ this->audio_channels = 2;
+ if (this->width && this->height)
+ break;
+ }
+ }
+
+ /* skip the rest of the chunk */
+ this->input->seek(this->input, chunk_size, SEEK_CUR);
+ }
+
+ /* after all is said and done, if there is a width and a height,
+ * regard it as being a valid file and reset to the first chunk */
+ if (this->width && this->height) {
+ this->input->seek(this->input, 8, SEEK_SET);
+ } else {
+ this->status = DEMUX_FINISHED;
+ pthread_mutex_unlock(&this->mutex);
+ return DEMUX_CANNOT_HANDLE;
+ }
+
+ /* load stream information */
+ this->xine->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->width;
+ this->xine->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->height;
+ this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] =
+ this->audio_channels;
+ this->xine->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] =
+ RoQ_AUDIO_SAMPLE_RATE;
+ this->xine->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = 16;
+
+ xine_demux_control_headers_done (this->xine);
+
+ pthread_mutex_unlock (&this->mutex);
+
+ return DEMUX_CAN_HANDLE;
+}
+
static int demux_roq_open(demux_plugin_t *this_gen, input_plugin_t *input,
int stage) {
demux_roq_t *this = (demux_roq_t *) this_gen;
@@ -270,7 +372,7 @@ static int demux_roq_open(demux_plugin_t *this_gen, input_plugin_t *input,
/* check for the RoQ magic numbers */
if ((LE_16(&preamble[0]) == RoQ_MAGIC_NUMBER) &&
(LE_32(&preamble[2]) == 0xFFFFFFFF))
- return DEMUX_CAN_HANDLE;
+ return load_roq_and_send_headers(this);
return DEMUX_CANNOT_HANDLE;
}
@@ -296,10 +398,8 @@ static int demux_roq_open(demux_plugin_t *this_gen, input_plugin_t *input,
while(*m == ' ' || *m == '\t') m++;
- if(!strcasecmp((suffix + 1), m)) {
- this->input = input;
- return DEMUX_CAN_HANDLE;
- }
+ if(!strcasecmp((suffix + 1), m))
+ return load_roq_and_send_headers(this);
}
return DEMUX_CANNOT_HANDLE;
}
@@ -315,108 +415,23 @@ static int demux_roq_open(demux_plugin_t *this_gen, input_plugin_t *input,
}
static int demux_roq_start (demux_plugin_t *this_gen,
- fifo_buffer_t *video_fifo,
- fifo_buffer_t *audio_fifo,
off_t start_pos, int start_time) {
demux_roq_t *this = (demux_roq_t *) this_gen;
buf_element_t *buf;
int err;
- char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
- int i;
- unsigned int chunk_type;
- unsigned int chunk_size;
pthread_mutex_lock(&this->mutex);
/* if thread is not running, initialize demuxer */
if (!this->thread_running) {
- this->video_fifo = video_fifo;
- this->audio_fifo = audio_fifo;
-
- this->input->seek(this->input, 0, SEEK_SET);
- if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
- RoQ_CHUNK_PREAMBLE_SIZE) {
- this->status = DEMUX_FINISHED;
- pthread_mutex_unlock(&this->mutex);
- return this->status;
- }
-
- this->width = this->height = 0;
- this->audio_channels = 0; /* assume no audio at first */
-
- /*
- * RoQ files enjoy a constant framerate; pts calculation:
- *
- * xine pts frame #
- * -------- = ------- => xine pts = 90000 * frame # / fps
- * 90000 fps
- *
- * therefore, the frame pts increment is 90000 / fps
- */
- this->fps = LE_16(&preamble[6]);
- this->frame_pts_inc = 90000 / this->fps;
-
- /* iterate through the first 2 seconds worth of chunks searching for
- * the RoQ_INFO chunk and an audio chunk */
- i = this->fps * 2;
- while (i-- > 0) {
- /* if this read fails, then maybe it's just a really small RoQ file
- * (even less than 2 seconds) */
- if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
- RoQ_CHUNK_PREAMBLE_SIZE)
- break;
- chunk_type = LE_16(&preamble[0]);
- chunk_size = LE_32(&preamble[2]);
-
- if (chunk_type == RoQ_INFO) {
- /* fetch the width and height; reuse the preamble bytes */
- if (this->input->read(this->input, preamble, 8) != 8)
- break;
-
- this->width = LE_16(&preamble[0]);
- this->height = LE_16(&preamble[2]);
-
- /* if an audio chunk was already found, search is done */
- if (this->audio_channels)
- break;
-
- /* prep the size for a seek */
- chunk_size -= 8;
- } else {
- /* if it was an audio chunk and the info chunk has already been
- * found (as indicated by width and height) then break */
- if (chunk_type == RoQ_SOUND_MONO) {
- this->audio_channels = 1;
- if (this->width && this->height)
- break;
- } else if (chunk_type == RoQ_SOUND_STEREO) {
- this->audio_channels = 2;
- if (this->width && this->height)
- break;
- }
- }
-
- /* skip the rest of the chunk */
- this->input->seek(this->input, chunk_size, SEEK_CUR);
- }
-
- /* after all is said and done, if there is a width and a height,
- * regard it as being a valid file and reset to the first chunk */
- if (this->width && this->height) {
- this->input->seek(this->input, 8, SEEK_SET);
- } else {
- this->status = DEMUX_FINISHED;
- pthread_mutex_unlock(&this->mutex);
- return this->status;
- }
/* print vital stats */
- xine_log (this->xine, XINE_LOG_FORMAT,
+ xine_log (this->xine, XINE_LOG_MSG,
_("demux_roq: RoQ file, video is %dx%d, %d frames/sec\n"),
this->width, this->height, this->fps);
if (this->audio_channels)
- xine_log (this->xine, XINE_LOG_FORMAT,
+ xine_log (this->xine, XINE_LOG_MSG,
_("demux_roq: 16-bit, 22050 Hz %s RoQ DPCM audio\n"),
(this->audio_channels == 1) ? "monaural" : "stereo");
@@ -500,7 +515,7 @@ static void demux_roq_stop (demux_plugin_t *this_gen) {
xine_demux_control_end(this->xine, BUF_FLAG_END_USER);
}
-static void demux_roq_close (demux_plugin_t *this) {
+static void demux_roq_dispose (demux_plugin_t *this) {
free(this);
}
@@ -540,7 +555,7 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) {
this->demux_plugin.start = demux_roq_start;
this->demux_plugin.seek = demux_roq_seek;
this->demux_plugin.stop = demux_roq_stop;
- this->demux_plugin.close = demux_roq_close;
+ this->demux_plugin.dispose = demux_roq_dispose;
this->demux_plugin.get_status = demux_roq_get_status;
this->demux_plugin.get_identifier = demux_roq_get_id;
this->demux_plugin.get_stream_length = demux_roq_get_stream_length;
@@ -558,6 +573,6 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) {
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_DEMUX, 10, "roq", XINE_VERSION_CODE, NULL, init_demuxer_plugin },
+ { PLUGIN_DEMUX, 11, "roq", XINE_VERSION_CODE, NULL, init_demuxer_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};