1 /*
2  * Copyright (C) 2000-2018 the xine project
3  *
4  * This file is part of xine, a free video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  */
20 
21 /*
22  * SMJPEG File Demuxer by Mike Melanson (melanson@pcisys.net)
23  * For more information on the SMJPEG file format, visit:
24  *   http://www.lokigames.com/development/smjpeg.php3
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include <stdio.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <stdlib.h>
36 
37 /********** logging **********/
38 #define LOG_MODULE "demux_smjpeg"
39 /* #define LOG_VERBOSE */
40 /* #define LOG */
41 
42 #include <xine/xine_internal.h>
43 #include <xine/xineutils.h>
44 #include <xine/compat.h>
45 #include <xine/demux.h>
46 #include "bswap.h"
47 #include "group_games.h"
48 
49 #define FOURCC_TAG BE_FOURCC
50 #define _TXT_TAG FOURCC_TAG('_', 'T', 'X', 'T')
51 #define _SND_TAG FOURCC_TAG('_', 'S', 'N', 'D')
52 #define _VID_TAG FOURCC_TAG('_', 'V', 'I', 'D')
53 #define HEND_TAG FOURCC_TAG('H', 'E', 'N', 'D')
54 #define sndD_TAG FOURCC_TAG('s', 'n', 'd', 'D')
55 #define vidD_TAG FOURCC_TAG('v', 'i', 'd', 'D')
56 #define APCM_TAG FOURCC_TAG('A', 'P', 'C', 'M')
57 
58 /* 16 is the max size of a header chunk (the video header) */
59 #define SMJPEG_VIDEO_HEADER_SIZE 16
60 #define SMJPEG_AUDIO_HEADER_SIZE 12
61 #define SMJPEG_HEADER_CHUNK_MAX_SIZE SMJPEG_VIDEO_HEADER_SIZE
62 #define SMJPEG_CHUNK_PREAMBLE_SIZE 12
63 
64 typedef struct {
65   demux_plugin_t       demux_plugin;
66 
67   xine_stream_t       *stream;
68   fifo_buffer_t       *video_fifo;
69   fifo_buffer_t       *audio_fifo;
70   input_plugin_t      *input;
71   int                  status;
72 
73   off_t                input_length;
74 
75   /* video information */
76   unsigned int         video_type;
77   xine_bmiheader       bih;
78 
79   /* audio information */
80   unsigned int         audio_type;
81   unsigned int         audio_sample_rate;
82   unsigned int         audio_bits;
83   unsigned int         audio_channels;
84 
85   /* playback information */
86   unsigned int         duration;  /* duration in milliseconds */
87 } demux_smjpeg_t;
88 
89 
90 /* returns 1 if the SMJPEG file was opened successfully, 0 otherwise */
open_smjpeg_file(demux_smjpeg_t * this)91 static int open_smjpeg_file(demux_smjpeg_t *this) {
92   unsigned int  chunk_tag;
93   unsigned char signature[8];
94   unsigned char header_chunk[SMJPEG_HEADER_CHUNK_MAX_SIZE];
95   uint32_t      audio_codec = 0;
96 
97   static const uint8_t SMJPEG_SIGNATURE[8] =
98     { 0x00, 0x0A, 'S', 'M', 'J', 'P', 'E', 'G' };
99 
100   if (_x_demux_read_header(this->input, signature, sizeof(SMJPEG_SIGNATURE)) !=
101       sizeof(SMJPEG_SIGNATURE))
102     return 0;
103 
104   if (memcmp(signature, SMJPEG_SIGNATURE, sizeof(SMJPEG_SIGNATURE)) != 0)
105     return 0;
106 
107   /* file is qualified; jump over the header + version to the duration */
108   if (this->input->seek(this->input, sizeof(SMJPEG_SIGNATURE) + 4, SEEK_SET) < 0)
109     return 0;
110   if (this->input->read(this->input, header_chunk, 4) != 4)
111     return 0;
112   this->duration = _X_BE_32(&header_chunk[0]);
113 
114   /* initial state: no video and no audio (until headers found) */
115   this->video_type = this->audio_type = 0;
116   this->input_length = this->input->get_length (this->input);
117 
118   /* traverse the header chunks until the HEND tag is found */
119   chunk_tag = 0;
120   while (chunk_tag != HEND_TAG) {
121 
122     if (this->input->read(this->input, header_chunk, 4) != 4)
123       return 0;
124     chunk_tag = _X_BE_32(&header_chunk[0]);
125 
126     switch(chunk_tag) {
127 
128     case HEND_TAG:
129       /* this indicates the end of the header; do nothing and fall
130        * out of the loop on the next iteration */
131       break;
132 
133     case _VID_TAG:
134       if (this->input->read(this->input, header_chunk,
135           SMJPEG_VIDEO_HEADER_SIZE) != SMJPEG_VIDEO_HEADER_SIZE)
136         return 0;
137 
138       this->bih.biWidth = _X_BE_16(&header_chunk[8]);
139       this->bih.biHeight = _X_BE_16(&header_chunk[10]);
140       memcpy(&this->bih.biCompression, &header_chunk[12], sizeof(uint32_t));
141       this->video_type = _x_fourcc_to_buf_video(this->bih.biCompression);
142       if (!this->video_type)
143         _x_report_video_fourcc (this->stream->xine, LOG_MODULE, this->bih.biCompression);
144       break;
145 
146     case _SND_TAG:
147       if (this->input->read(this->input, header_chunk,
148           SMJPEG_AUDIO_HEADER_SIZE) != SMJPEG_AUDIO_HEADER_SIZE)
149         return 0;
150 
151       this->audio_sample_rate = _X_BE_16(&header_chunk[4]);
152       this->audio_bits = header_chunk[6];
153       this->audio_channels = header_chunk[7];
154       /* ADPCM in these files is ID'd by 'APCM' which is used in other
155        * files to denote a slightly different format; thus, use the
156        * following special case */
157       if (_X_BE_32(&header_chunk[8]) == APCM_TAG) {
158         audio_codec = be2me_32(APCM_TAG);
159         this->audio_type = BUF_AUDIO_SMJPEG_IMA;
160       } else {
161         memcpy(&audio_codec, &header_chunk[8], sizeof(uint32_t));
162         this->audio_type = _x_formattag_to_buf_audio(audio_codec);
163         if (!this->audio_type)
164           _x_report_audio_format_tag (this->stream->xine, LOG_MODULE, audio_codec);
165       }
166       break;
167 
168     default:
169       /* for all other chunk types, read the length and skip the rest
170        * of the chunk */
171       if (this->input->read(this->input, header_chunk, 4) != 4)
172         return 0;
173       if (this->input->seek(this->input, _X_BE_32(&header_chunk[0]), SEEK_CUR) < 0)
174         return 0;
175       break;
176     }
177   }
178 
179   if(!this->video_type)
180     this->video_type = BUF_VIDEO_UNKNOWN;
181 
182   if(!this->audio_type && audio_codec)
183     this->audio_type = BUF_AUDIO_UNKNOWN;
184 
185   return 1;
186 }
187 
demux_smjpeg_send_chunk(demux_plugin_t * this_gen)188 static int demux_smjpeg_send_chunk(demux_plugin_t *this_gen) {
189   demux_smjpeg_t *this = (demux_smjpeg_t *) this_gen;
190 
191   buf_element_t *buf = NULL;
192   unsigned int chunk_tag;
193   int64_t pts;
194   unsigned int remaining_sample_bytes;
195   unsigned char preamble[SMJPEG_CHUNK_PREAMBLE_SIZE];
196   off_t current_file_pos;
197   int64_t last_frame_pts = 0;
198   unsigned int audio_frame_count = 0;
199 
200   /* load the next sample */
201   current_file_pos = this->input->get_current_pos(this->input);
202   if (this->input->read(this->input, preamble,
203     SMJPEG_CHUNK_PREAMBLE_SIZE) != SMJPEG_CHUNK_PREAMBLE_SIZE) {
204     this->status = DEMUX_FINISHED;
205     return this->status;  /* skip to next while() iteration to bail out */
206   }
207 
208   chunk_tag = _X_BE_32(&preamble[0]);
209   remaining_sample_bytes = _X_BE_32(&preamble[8]);
210 
211   /*
212    * Each sample has an absolute timestamp in millisecond units:
213    *
214    *    xine pts     timestamp (ms)
215    *    --------  =  --------------
216    *      90000           1000
217    *
218    * therefore, xine pts = timestamp * 90000 / 1000 => timestamp * 90
219    *
220    * However, millisecond timestamps are not completely accurate
221    * for the audio samples. These audio chunks usually have 256 bytes,
222    * or 512 nibbles, which corresponds to 512 samples.
223    *
224    *   512 samples * (1 sec / 22050 samples) * (1000 ms / 1 sec)
225    *     = 23.2 ms
226    *
227    * where the audio samples claim that each chunk is 23 ms long.
228    * Therefore, manually compute the pts values for the audio samples.
229    */
230   if (chunk_tag == sndD_TAG) {
231     pts = audio_frame_count;
232     pts *= 90000;
233     pts /= (this->audio_sample_rate * this->audio_channels);
234     audio_frame_count += ((remaining_sample_bytes - 4) * 2);
235   } else {
236     pts = _X_BE_32(&preamble[4]);
237     pts *= 90;
238   }
239 
240   /* break up the data into packets and dispatch them */
241   if (((chunk_tag == sndD_TAG) && this->audio_fifo && this->audio_type) ||
242     (chunk_tag == vidD_TAG)) {
243 
244     while (remaining_sample_bytes) {
245       if (chunk_tag == sndD_TAG) {
246         buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
247         buf->type = this->audio_type;
248       } else {
249         buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
250         buf->type = this->video_type;
251       }
252 
253       if( this->input_length )
254         buf->extra_info->input_normpos = (int)( (double) current_file_pos * 65535 / this->input_length);
255       buf->extra_info->input_time = pts / 90;
256       buf->pts = pts;
257 
258       if (last_frame_pts) {
259         buf->decoder_flags |= BUF_FLAG_FRAMERATE;
260         buf->decoder_info[0] = buf->pts - last_frame_pts;
261       }
262 
263       if ((int)remaining_sample_bytes > buf->max_size)
264         buf->size = buf->max_size;
265       else
266         buf->size = remaining_sample_bytes;
267       remaining_sample_bytes -= buf->size;
268 
269       if (this->input->read(this->input, buf->content, buf->size) !=
270         buf->size) {
271         buf->free_buffer(buf);
272         this->status = DEMUX_FINISHED;
273         break;
274       }
275 
276       /* every frame is a keyframe */
277       buf->decoder_flags |= BUF_FLAG_KEYFRAME;
278       if (!remaining_sample_bytes)
279         buf->decoder_flags |= BUF_FLAG_FRAME_END;
280 
281       if (chunk_tag == sndD_TAG)
282         this->audio_fifo->put(this->audio_fifo, buf);
283       else
284         this->video_fifo->put(this->video_fifo, buf);
285     }
286 
287   } else {
288 
289     /* skip the chunk if it can't be handled */
290     if (this->input->seek(this->input, remaining_sample_bytes, SEEK_CUR) < 0) {
291       this->status = DEMUX_FINISHED;
292       return this->status;
293     }
294   }
295 
296   if (chunk_tag == vidD_TAG)
297     last_frame_pts = buf->pts;
298 
299   return this->status;
300 }
301 
demux_smjpeg_send_headers(demux_plugin_t * this_gen)302 static void demux_smjpeg_send_headers(demux_plugin_t *this_gen) {
303   demux_smjpeg_t *this = (demux_smjpeg_t *) this_gen;
304   buf_element_t *buf;
305 
306   this->video_fifo  = this->stream->video_fifo;
307   this->audio_fifo  = this->stream->audio_fifo;
308 
309   this->status = DEMUX_OK;
310 
311   /* load stream information */
312   _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
313   _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO,
314                        (this->audio_channels) ? 1 : 0);
315   _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH,
316                        this->bih.biWidth);
317   _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT,
318                        this->bih.biHeight);
319   _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_CHANNELS,
320                        this->audio_channels);
321   _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE,
322                        this->audio_sample_rate);
323   _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS,
324                        this->audio_bits);
325 
326   /* send start buffers */
327   _x_demux_control_start(this->stream);
328 
329   /* send init info to decoders */
330   buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
331   buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAMERATE|
332                        BUF_FLAG_FRAME_END;
333   buf->decoder_info[0] = 3000;  /* initial video_step */
334   memcpy(buf->content, &this->bih, sizeof(this->bih));
335   buf->size = sizeof(this->bih);
336   buf->type = this->video_type;
337   this->video_fifo->put (this->video_fifo, buf);
338 
339   if (this->audio_fifo && this->audio_type) {
340     buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
341     buf->type = this->audio_type;
342     buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
343     buf->decoder_info[0] = 0;
344     buf->decoder_info[1] = this->audio_sample_rate;
345     buf->decoder_info[2] = this->audio_bits;
346     buf->decoder_info[3] = this->audio_channels;
347     this->audio_fifo->put (this->audio_fifo, buf);
348   }
349 }
350 
demux_smjpeg_seek(demux_plugin_t * this_gen,off_t start_pos,int start_time,int playing)351 static int demux_smjpeg_seek (demux_plugin_t *this_gen, off_t start_pos, int start_time, int playing) {
352   demux_smjpeg_t *this = (demux_smjpeg_t *) this_gen;
353 
354   (void)start_pos;
355   (void)start_time;
356 
357   /* if thread is not running, initialize demuxer */
358   if( !playing ) {
359 
360     this->status = DEMUX_OK;
361   }
362 
363   return this->status;
364 }
365 
366 
demux_smjpeg_get_status(demux_plugin_t * this_gen)367 static int demux_smjpeg_get_status (demux_plugin_t *this_gen) {
368   demux_smjpeg_t *this = (demux_smjpeg_t *) this_gen;
369 
370   return this->status;
371 }
372 
demux_smjpeg_get_stream_length(demux_plugin_t * this_gen)373 static int demux_smjpeg_get_stream_length (demux_plugin_t *this_gen) {
374   demux_smjpeg_t *this = (demux_smjpeg_t *) this_gen;
375 
376   /* return total running time in miliseconds */
377   return this->duration;
378 }
379 
demux_smjpeg_get_capabilities(demux_plugin_t * this_gen)380 static uint32_t demux_smjpeg_get_capabilities(demux_plugin_t *this_gen) {
381   (void)this_gen;
382   return DEMUX_CAP_NOCAP;
383 }
384 
demux_smjpeg_get_optional_data(demux_plugin_t * this_gen,void * data,int data_type)385 static int demux_smjpeg_get_optional_data(demux_plugin_t *this_gen,
386 					void *data, int data_type) {
387   (void)this_gen;
388   (void)data;
389   (void)data_type;
390   return DEMUX_OPTIONAL_UNSUPPORTED;
391 }
392 
open_plugin(demux_class_t * class_gen,xine_stream_t * stream,input_plugin_t * input)393 static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream,
394                                     input_plugin_t *input) {
395 
396   demux_smjpeg_t *this;
397 
398   if (!INPUT_IS_SEEKABLE(input)) {
399     xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "input not seekable, can not handle!\n");
400     return NULL;
401   }
402 
403   this = calloc(1, sizeof(demux_smjpeg_t));
404   if (!this)
405     return NULL;
406 
407   this->stream = stream;
408   this->input  = input;
409 
410   this->demux_plugin.send_headers      = demux_smjpeg_send_headers;
411   this->demux_plugin.send_chunk        = demux_smjpeg_send_chunk;
412   this->demux_plugin.seek              = demux_smjpeg_seek;
413   this->demux_plugin.dispose           = default_demux_plugin_dispose;
414   this->demux_plugin.get_status        = demux_smjpeg_get_status;
415   this->demux_plugin.get_stream_length = demux_smjpeg_get_stream_length;
416   this->demux_plugin.get_capabilities  = demux_smjpeg_get_capabilities;
417   this->demux_plugin.get_optional_data = demux_smjpeg_get_optional_data;
418   this->demux_plugin.demux_class       = class_gen;
419 
420   this->status = DEMUX_FINISHED;
421 
422   switch (stream->content_detection_method) {
423 
424   case METHOD_BY_MRL:
425   case METHOD_BY_CONTENT:
426   case METHOD_EXPLICIT:
427 
428     if (!open_smjpeg_file(this)) {
429       free (this);
430       return NULL;
431     }
432 
433   break;
434 
435   default:
436     free (this);
437     return NULL;
438   }
439 
440   return &this->demux_plugin;
441 }
442 
demux_smjpeg_init_plugin(xine_t * xine,const void * data)443 void *demux_smjpeg_init_plugin (xine_t *xine, const void *data) {
444 
445   (void)xine;
446   (void)data;
447 
448   static const demux_class_t demux_smjpeg_class = {
449     .open_plugin     = open_plugin,
450     .description     = N_("SMJPEG file demux plugin"),
451     .identifier      = "SMJPEG",
452     .mimetypes       = NULL,
453     .extensions      = "mjpg",
454     .dispose         = NULL,
455   };
456 
457   return (void *)&demux_smjpeg_class;
458 }
459