1 /*
2  * Silicon Graphics Movie demuxer
3  * Copyright (c) 2012 Peter Ross
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * Silicon Graphics Movie demuxer
25  */
26 
27 #include "libavutil/channel_layout.h"
28 #include "libavutil/eval.h"
29 #include "libavutil/intfloat.h"
30 #include "libavutil/intreadwrite.h"
31 #include "libavutil/rational.h"
32 
33 #include "avformat.h"
34 #include "internal.h"
35 
36 typedef struct MvContext {
37     int nb_video_tracks;
38     int nb_audio_tracks;
39 
40     int eof_count;        ///< number of streams that have finished
41     int stream_index;     ///< current stream index
42     int frame[2];         ///< frame nb for current stream
43 
44     int acompression;     ///< compression level for audio stream
45     int aformat;          ///< audio format
46 } MvContext;
47 
48 /* these magic numbers are defined in moviefile.h on Silicon Grahpics IRIX */
49 #define MOVIE_SOUND  1
50 #define MOVIE_SILENT 2
51 
52 #define AUDIO_FORMAT_SIGNED 401
53 
mv_probe(const AVProbeData *p)54 static int mv_probe(const AVProbeData *p)
55 {
56     if (AV_RB32(p->buf) == MKBETAG('M', 'O', 'V', 'I') &&
57         AV_RB16(p->buf + 4) < 3)
58         return AVPROBE_SCORE_MAX;
59     return 0;
60 }
61 
var_read_string(AVIOContext *pb, int size)62 static char *var_read_string(AVIOContext *pb, int size)
63 {
64     int n;
65     char *str;
66 
67     if (size < 0 || size == INT_MAX)
68         return NULL;
69 
70     str = av_malloc(size + 1);
71     if (!str)
72         return NULL;
73     n = avio_get_str(pb, size, str, size + 1);
74     if (n < size)
75         avio_skip(pb, size - n);
76     return str;
77 }
78 
var_read_int(AVIOContext *pb, int size)79 static int var_read_int(AVIOContext *pb, int size)
80 {
81     int v;
82     char *s = var_read_string(pb, size);
83     if (!s)
84         return 0;
85     v = strtol(s, NULL, 10);
86     av_free(s);
87     return v;
88 }
89 
var_read_float(AVIOContext *pb, int size)90 static AVRational var_read_float(AVIOContext *pb, int size)
91 {
92     AVRational v;
93     char *s = var_read_string(pb, size);
94     if (!s)
95         return (AVRational) { 0, 0 };
96     v = av_d2q(av_strtod(s, NULL), INT_MAX);
97     av_free(s);
98     return v;
99 }
100 
var_read_metadata(AVFormatContext *avctx, const char *tag, int size)101 static void var_read_metadata(AVFormatContext *avctx, const char *tag, int size)
102 {
103     char *value = var_read_string(avctx->pb, size);
104     if (value)
105         av_dict_set(&avctx->metadata, tag, value, AV_DICT_DONT_STRDUP_VAL);
106 }
107 
set_channels(AVFormatContext *avctx, AVStream *st, int channels)108 static int set_channels(AVFormatContext *avctx, AVStream *st, int channels)
109 {
110     if (channels <= 0) {
111         av_log(avctx, AV_LOG_ERROR, "Channel count %d invalid.\n", channels);
112         return AVERROR_INVALIDDATA;
113     }
114     av_channel_layout_default(&st->codecpar->ch_layout, channels);
115     return 0;
116 }
117 
118 /**
119  * Parse global variable
120  * @return < 0 if unknown
121  */
parse_global_var(AVFormatContext *avctx, AVStream *st, const char *name, int size)122 static int parse_global_var(AVFormatContext *avctx, AVStream *st,
123                             const char *name, int size)
124 {
125     MvContext *mv = avctx->priv_data;
126     AVIOContext *pb = avctx->pb;
127     if (!strcmp(name, "__NUM_I_TRACKS")) {
128         mv->nb_video_tracks = var_read_int(pb, size);
129     } else if (!strcmp(name, "__NUM_A_TRACKS")) {
130         mv->nb_audio_tracks = var_read_int(pb, size);
131     } else if (!strcmp(name, "COMMENT") || !strcmp(name, "TITLE")) {
132         var_read_metadata(avctx, name, size);
133     } else if (!strcmp(name, "LOOP_MODE") || !strcmp(name, "NUM_LOOPS") ||
134                !strcmp(name, "OPTIMIZED")) {
135         avio_skip(pb, size); // ignore
136     } else
137         return AVERROR_INVALIDDATA;
138 
139     return 0;
140 }
141 
142 /**
143  * Parse audio variable
144  * @return < 0 if unknown
145  */
parse_audio_var(AVFormatContext *avctx, AVStream *st, const char *name, int size)146 static int parse_audio_var(AVFormatContext *avctx, AVStream *st,
147                            const char *name, int size)
148 {
149     MvContext *mv = avctx->priv_data;
150     AVIOContext *pb = avctx->pb;
151     if (!strcmp(name, "__DIR_COUNT")) {
152         st->nb_frames = var_read_int(pb, size);
153     } else if (!strcmp(name, "AUDIO_FORMAT")) {
154         mv->aformat = var_read_int(pb, size);
155     } else if (!strcmp(name, "COMPRESSION")) {
156         mv->acompression = var_read_int(pb, size);
157     } else if (!strcmp(name, "DEFAULT_VOL")) {
158         var_read_metadata(avctx, name, size);
159     } else if (!strcmp(name, "NUM_CHANNELS")) {
160         return set_channels(avctx, st, var_read_int(pb, size));
161     } else if (!strcmp(name, "SAMPLE_RATE")) {
162         int sample_rate = var_read_int(pb, size);
163         if (sample_rate <= 0)
164             return AVERROR_INVALIDDATA;
165         st->codecpar->sample_rate = sample_rate;
166         avpriv_set_pts_info(st, 33, 1, st->codecpar->sample_rate);
167     } else if (!strcmp(name, "SAMPLE_WIDTH")) {
168         uint64_t bpc = var_read_int(pb, size) * (uint64_t)8;
169         if (bpc > 16)
170             return AVERROR_INVALIDDATA;
171         st->codecpar->bits_per_coded_sample = bpc;
172     } else
173         return AVERROR_INVALIDDATA;
174 
175     return 0;
176 }
177 
178 /**
179  * Parse video variable
180  * @return < 0 if unknown
181  */
parse_video_var(AVFormatContext *avctx, AVStream *st, const char *name, int size)182 static int parse_video_var(AVFormatContext *avctx, AVStream *st,
183                            const char *name, int size)
184 {
185     AVIOContext *pb = avctx->pb;
186     if (!strcmp(name, "__DIR_COUNT")) {
187         st->nb_frames = st->duration = var_read_int(pb, size);
188     } else if (!strcmp(name, "COMPRESSION")) {
189         char *str = var_read_string(pb, size);
190         if (!str)
191             return AVERROR_INVALIDDATA;
192         if (!strcmp(str, "1")) {
193             st->codecpar->codec_id = AV_CODEC_ID_MVC1;
194         } else if (!strcmp(str, "2")) {
195             st->codecpar->format = AV_PIX_FMT_ABGR;
196             st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
197         } else if (!strcmp(str, "3")) {
198             st->codecpar->codec_id = AV_CODEC_ID_SGIRLE;
199         } else if (!strcmp(str, "10")) {
200             st->codecpar->codec_id = AV_CODEC_ID_MJPEG;
201         } else if (!strcmp(str, "MVC2")) {
202             st->codecpar->codec_id = AV_CODEC_ID_MVC2;
203         } else {
204             avpriv_request_sample(avctx, "Video compression %s", str);
205         }
206         av_free(str);
207     } else if (!strcmp(name, "FPS")) {
208         AVRational fps = var_read_float(pb, size);
209         avpriv_set_pts_info(st, 64, fps.den, fps.num);
210         st->avg_frame_rate = fps;
211     } else if (!strcmp(name, "HEIGHT")) {
212         st->codecpar->height = var_read_int(pb, size);
213     } else if (!strcmp(name, "PIXEL_ASPECT")) {
214         st->sample_aspect_ratio = var_read_float(pb, size);
215         av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
216                   st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
217                   INT_MAX);
218     } else if (!strcmp(name, "WIDTH")) {
219         st->codecpar->width = var_read_int(pb, size);
220     } else if (!strcmp(name, "ORIENTATION")) {
221         if (var_read_int(pb, size) == 1101) {
222             if (!st->codecpar->extradata) {
223                 st->codecpar->extradata = av_strdup("BottomUp");
224                 if (!st->codecpar->extradata)
225                     return AVERROR(ENOMEM);
226                 st->codecpar->extradata_size = 9;
227             }
228         }
229     } else if (!strcmp(name, "Q_SPATIAL") || !strcmp(name, "Q_TEMPORAL")) {
230         var_read_metadata(avctx, name, size);
231     } else if (!strcmp(name, "INTERLACING") || !strcmp(name, "PACKING")) {
232         avio_skip(pb, size); // ignore
233     } else
234         return AVERROR_INVALIDDATA;
235 
236     return 0;
237 }
238 
read_table(AVFormatContext *avctx, AVStream *st, int (*parse)(AVFormatContext *avctx, AVStream *st, const char *name, int size))239 static int read_table(AVFormatContext *avctx, AVStream *st,
240                        int (*parse)(AVFormatContext *avctx, AVStream *st,
241                                     const char *name, int size))
242 {
243     unsigned count;
244     int i;
245 
246     AVIOContext *pb = avctx->pb;
247     avio_skip(pb, 4);
248     count = avio_rb32(pb);
249     avio_skip(pb, 4);
250     for (i = 0; i < count; i++) {
251         char name[17];
252         int size;
253 
254         if (avio_feof(pb))
255             return AVERROR_EOF;
256 
257         avio_read(pb, name, 16);
258         name[sizeof(name) - 1] = 0;
259         size = avio_rb32(pb);
260         if (size < 0) {
261             av_log(avctx, AV_LOG_ERROR, "entry size %d is invalid\n", size);
262             return AVERROR_INVALIDDATA;
263         }
264         if (parse(avctx, st, name, size) < 0) {
265             avpriv_request_sample(avctx, "Variable %s", name);
266             avio_skip(pb, size);
267         }
268     }
269     return 0;
270 }
271 
read_index(AVIOContext *pb, AVStream *st)272 static void read_index(AVIOContext *pb, AVStream *st)
273 {
274     uint64_t timestamp = 0;
275     int i;
276     for (i = 0; i < st->nb_frames; i++) {
277         uint32_t pos  = avio_rb32(pb);
278         uint32_t size = avio_rb32(pb);
279         avio_skip(pb, 8);
280         if (avio_feof(pb))
281             return ;
282         av_add_index_entry(st, pos, timestamp, size, 0, AVINDEX_KEYFRAME);
283         if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
284             timestamp += size / (st->codecpar->ch_layout.nb_channels * 2LL);
285         } else {
286             timestamp++;
287         }
288     }
289 }
290 
mv_read_header(AVFormatContext *avctx)291 static int mv_read_header(AVFormatContext *avctx)
292 {
293     MvContext *mv = avctx->priv_data;
294     AVIOContext *pb = avctx->pb;
295     AVStream *ast = NULL, *vst = NULL; //initialization to suppress warning
296     int version, i;
297     int ret;
298 
299     avio_skip(pb, 4);
300 
301     version = avio_rb16(pb);
302     if (version == 2) {
303         uint64_t timestamp;
304         int v;
305         uint32_t bytes_per_sample;
306         AVRational fps;
307 
308         avio_skip(pb, 10);
309 
310         fps = av_d2q(av_int2double(avio_rb64(pb)), INT_MAX);
311 
312         /* allocate audio track first to prevent unnecessary seeking
313          * (audio packet always precede video packet for a given frame) */
314         v = avio_rb16(pb);
315         if (v == MOVIE_SOUND) {
316             /* movie has sound so allocate an audio stream */
317             ast = avformat_new_stream(avctx, NULL);
318             if (!ast)
319                 return AVERROR(ENOMEM);
320         } else if (v != MOVIE_SILENT)
321             return AVERROR_INVALIDDATA;
322 
323         avio_skip(pb, 2);
324 
325         vst = avformat_new_stream(avctx, NULL);
326         if (!vst)
327             return AVERROR(ENOMEM);
328         avpriv_set_pts_info(vst, 64, fps.den, fps.num);
329         vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
330         vst->avg_frame_rate = fps;
331         vst->duration = vst->nb_frames = avio_rb32(pb);
332         v = avio_rb32(pb);
333         switch (v) {
334         case 1:
335             vst->codecpar->codec_id = AV_CODEC_ID_MVC1;
336             break;
337         case 2:
338             vst->codecpar->format = AV_PIX_FMT_ARGB;
339             vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
340             break;
341         default:
342             avpriv_request_sample(avctx, "Video compression %i", v);
343             break;
344         }
345         vst->codecpar->codec_tag = 0;
346         vst->codecpar->width     = avio_rb32(pb);
347         vst->codecpar->height    = avio_rb32(pb);
348         avio_skip(pb, 12);
349 
350         if (ast) {
351             ast->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
352             ast->nb_frames = vst->nb_frames;
353             ast->codecpar->sample_rate = avio_rb32(pb);
354             if (ast->codecpar->sample_rate <= 0) {
355                 av_log(avctx, AV_LOG_ERROR, "Invalid sample rate %d\n", ast->codecpar->sample_rate);
356                 return AVERROR_INVALIDDATA;
357             }
358             avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate);
359 
360             bytes_per_sample = avio_rb32(pb);
361 
362             v = avio_rb32(pb);
363             if (v == AUDIO_FORMAT_SIGNED) {
364                 switch (bytes_per_sample) {
365                 case 1:
366                     ast->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
367                     break;
368                 case 2:
369                     ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
370                     break;
371                 default:
372                     avpriv_request_sample(avctx, "Audio sample size %i bytes", bytes_per_sample);
373                     break;
374                 }
375             } else {
376                 avpriv_request_sample(avctx, "Audio compression (format %i)", v);
377             }
378 
379             if (bytes_per_sample == 0)
380                 return AVERROR_INVALIDDATA;
381 
382             if (set_channels(avctx, ast, avio_rb32(pb)) < 0)
383                 return AVERROR_INVALIDDATA;
384 
385             avio_skip(pb, 8);
386         } else
387             avio_skip(pb, 24); /* skip meaningless audio metadata */
388 
389         var_read_metadata(avctx, "title", 0x80);
390         var_read_metadata(avctx, "comment", 0x100);
391         avio_skip(pb, 0x80);
392 
393         timestamp = 0;
394         for (i = 0; i < vst->nb_frames; i++) {
395             uint32_t pos   = avio_rb32(pb);
396             uint32_t asize = avio_rb32(pb);
397             uint32_t vsize = avio_rb32(pb);
398             if (avio_feof(pb))
399                 return AVERROR_INVALIDDATA;
400             avio_skip(pb, 8);
401             if (ast) {
402                 av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME);
403                 timestamp += asize / (ast->codecpar->ch_layout.nb_channels * (uint64_t)bytes_per_sample);
404             }
405             av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME);
406         }
407     } else if (!version && avio_rb16(pb) == 3) {
408         avio_skip(pb, 4);
409 
410         if ((ret = read_table(avctx, NULL, parse_global_var)) < 0)
411             return ret;
412 
413         if (mv->nb_audio_tracks < 0  || mv->nb_video_tracks < 0 ||
414            (mv->nb_audio_tracks == 0 && mv->nb_video_tracks == 0)) {
415             av_log(avctx, AV_LOG_ERROR, "Stream count is invalid.\n");
416             return AVERROR_INVALIDDATA;
417         }
418 
419         if (mv->nb_audio_tracks > 1) {
420             avpriv_request_sample(avctx, "Multiple audio streams support");
421             return AVERROR_PATCHWELCOME;
422         } else if (mv->nb_audio_tracks) {
423             ast = avformat_new_stream(avctx, NULL);
424             if (!ast)
425                 return AVERROR(ENOMEM);
426             ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
427             if ((ret = read_table(avctx, ast, parse_audio_var)) < 0)
428                 return ret;
429             if (mv->acompression == 100 &&
430                 mv->aformat == AUDIO_FORMAT_SIGNED &&
431                 ast->codecpar->bits_per_coded_sample == 16) {
432                 ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
433             } else {
434                 avpriv_request_sample(avctx,
435                                       "Audio compression %i (format %i, sr %i)",
436                                       mv->acompression, mv->aformat,
437                                       ast->codecpar->bits_per_coded_sample);
438                 ast->codecpar->codec_id = AV_CODEC_ID_NONE;
439             }
440             if (ast->codecpar->ch_layout.nb_channels <= 0) {
441                 av_log(avctx, AV_LOG_ERROR, "No valid channel count found.\n");
442                 return AVERROR_INVALIDDATA;
443             }
444         }
445 
446         if (mv->nb_video_tracks > 1) {
447             avpriv_request_sample(avctx, "Multiple video streams support");
448             return AVERROR_PATCHWELCOME;
449         } else if (mv->nb_video_tracks) {
450             vst = avformat_new_stream(avctx, NULL);
451             if (!vst)
452                 return AVERROR(ENOMEM);
453             vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
454             if ((ret = read_table(avctx, vst, parse_video_var))<0)
455                 return ret;
456         }
457 
458         if (mv->nb_audio_tracks)
459             read_index(pb, ast);
460 
461         if (mv->nb_video_tracks)
462             read_index(pb, vst);
463     } else {
464         avpriv_request_sample(avctx, "Version %i", version);
465         return AVERROR_PATCHWELCOME;
466     }
467 
468     return 0;
469 }
470 
mv_read_packet(AVFormatContext *avctx, AVPacket *pkt)471 static int mv_read_packet(AVFormatContext *avctx, AVPacket *pkt)
472 {
473     MvContext *mv = avctx->priv_data;
474     AVIOContext *pb = avctx->pb;
475     AVStream *st = avctx->streams[mv->stream_index];
476     FFStream *const sti = ffstream(st);
477     const AVIndexEntry *index;
478     int frame = mv->frame[mv->stream_index];
479     int64_t ret;
480     uint64_t pos;
481 
482     if (frame < sti->nb_index_entries) {
483         index = &sti->index_entries[frame];
484         pos   = avio_tell(pb);
485         if (index->pos > pos)
486             avio_skip(pb, index->pos - pos);
487         else if (index->pos < pos) {
488             if (!(pb->seekable & AVIO_SEEKABLE_NORMAL))
489                 return AVERROR(EIO);
490             ret = avio_seek(pb, index->pos, SEEK_SET);
491             if (ret < 0)
492                 return ret;
493         }
494         ret = av_get_packet(pb, pkt, index->size);
495         if (ret < 0)
496             return ret;
497 
498         pkt->stream_index = mv->stream_index;
499         pkt->pts          = index->timestamp;
500         pkt->flags       |= AV_PKT_FLAG_KEY;
501 
502         mv->frame[mv->stream_index]++;
503         mv->eof_count = 0;
504     } else {
505         mv->eof_count++;
506         if (mv->eof_count >= avctx->nb_streams)
507             return AVERROR_EOF;
508 
509         // avoid returning 0 without a packet
510         return AVERROR(EAGAIN);
511     }
512 
513     mv->stream_index++;
514     if (mv->stream_index >= avctx->nb_streams)
515         mv->stream_index = 0;
516 
517     return 0;
518 }
519 
mv_read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags)520 static int mv_read_seek(AVFormatContext *avctx, int stream_index,
521                         int64_t timestamp, int flags)
522 {
523     MvContext *mv = avctx->priv_data;
524     AVStream *st = avctx->streams[stream_index];
525     int frame, i;
526 
527     if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE))
528         return AVERROR(ENOSYS);
529 
530     if (!(avctx->pb->seekable & AVIO_SEEKABLE_NORMAL))
531         return AVERROR(EIO);
532 
533     frame = av_index_search_timestamp(st, timestamp, flags);
534     if (frame < 0)
535         return AVERROR_INVALIDDATA;
536 
537     for (i = 0; i < avctx->nb_streams; i++)
538         mv->frame[i] = frame;
539     return 0;
540 }
541 
542 const AVInputFormat ff_mv_demuxer = {
543     .name           = "mv",
544     .long_name      = NULL_IF_CONFIG_SMALL("Silicon Graphics Movie"),
545     .priv_data_size = sizeof(MvContext),
546     .read_probe     = mv_probe,
547     .read_header    = mv_read_header,
548     .read_packet    = mv_read_packet,
549     .read_seek      = mv_read_seek,
550 };
551