aboutsummaryrefslogtreecommitdiffhomepage
path: root/libmpdemux
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2012-07-30 18:40:46 +0200
committerGravatar wm4 <wm4@nowhere>2012-07-30 22:14:32 +0200
commit1fde09db6f4cee7347842261234082470dd3a2ca (patch)
treec05bf64b1b397a62e6f0b9cf295a6f9d0266eed2 /libmpdemux
parent17b69493b70413326c95c3c552009626809b45ec (diff)
Remove some demuxers and decoders
Most of these demuxers and decoders are provided in better form by libav, while the mplayer builtin ones are essentially unmaintained. The only legimitate use case for not using the libav ones was working around libav bugs or bugs related to the way mplayer uses libav. Instead of trying to keep dead code alive, development effort should go into improving libav or the mplayer libav glue code. Note that the libav demuxer have been preferred over the mplayer builtin ones for a while in mplayer2. There were some exceptions: playing DVDs with dvdnav or playing network sources. (That's because some stream modules and network.c requested explicit file formats, such as DEMUXER_TYPE_MPEG_PS, which mapped to builtin demuxers.) With this commit, they are switched to use libav. One caveat is that the requested format is not passed to libavformat, instead we rely on the auto probing to select the correct libav demuxer (see code in demux_open_stream()).
Diffstat (limited to 'libmpdemux')
-rw-r--r--libmpdemux/aac_hdr.c47
-rw-r--r--libmpdemux/aac_hdr.h26
-rw-r--r--libmpdemux/demux_aac.c260
-rw-r--r--libmpdemux/demux_avi.c39
-rw-r--r--libmpdemux/demux_film.c490
-rw-r--r--libmpdemux/demux_fli.c228
-rw-r--r--libmpdemux/demux_lmlm4.c385
-rw-r--r--libmpdemux/demux_mov.c2350
-rw-r--r--libmpdemux/demux_mov.h24
-rw-r--r--libmpdemux/demux_mpc.c235
-rw-r--r--libmpdemux/demux_mpg.c1248
-rw-r--r--libmpdemux/demux_nsv.c345
-rw-r--r--libmpdemux/demux_nut.c321
-rw-r--r--libmpdemux/demux_ogg.c1660
-rw-r--r--libmpdemux/demux_ogg.h27
-rw-r--r--libmpdemux/demux_pva.c536
-rw-r--r--libmpdemux/demux_roq.c281
-rw-r--r--libmpdemux/demux_smjpeg.c200
-rw-r--r--libmpdemux/demux_ts.c3533
-rw-r--r--libmpdemux/demux_ts.h24
-rw-r--r--libmpdemux/demux_ty.c899
-rw-r--r--libmpdemux/demux_ty_osd.c911
-rw-r--r--libmpdemux/demux_ty_osd.h25
-rw-r--r--libmpdemux/demux_vqf.c240
-rw-r--r--libmpdemux/demux_y4m.c325
-rw-r--r--libmpdemux/demuxer.c68
-rw-r--r--libmpdemux/demuxer.h17
-rw-r--r--libmpdemux/extension.c23
-rw-r--r--libmpdemux/mpeg_hdr.c539
-rw-r--r--libmpdemux/mpeg_hdr.h55
-rw-r--r--libmpdemux/parse_es.c158
-rw-r--r--libmpdemux/parse_es.h45
-rw-r--r--libmpdemux/parse_mp4.c173
-rw-r--r--libmpdemux/parse_mp4.h127
-rw-r--r--libmpdemux/video.c521
35 files changed, 32 insertions, 16353 deletions
diff --git a/libmpdemux/aac_hdr.c b/libmpdemux/aac_hdr.c
deleted file mode 100644
index 36991e27a2..0000000000
--- a/libmpdemux/aac_hdr.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2005 Nico Sabbi
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdint.h>
-#include "aac_hdr.h"
-#include "libavutil/attributes.h"
-
-/// \param srate (out) sample rate
-/// \param num (out) number of audio frames in this ADTS frame
-/// \return size of the ADTS frame in bytes
-/// aac_parse_frames needs a buffer at least 8 bytes long
-int aac_parse_frame(uint8_t *buf, int *srate, int *num)
-{
- int i = 0, sr, fl = 0, id av_unused;
- static int srates[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0, 0, 0};
-
- if((buf[i] != 0xFF) || ((buf[i+1] & 0xF6) != 0xF0))
- return 0;
-
- id = (buf[i+1] >> 3) & 0x01; //id=1 mpeg2, 0: mpeg4
- sr = (buf[i+2] >> 2) & 0x0F;
- if(sr > 11)
- return 0;
- *srate = srates[sr];
-
- fl = ((buf[i+3] & 0x03) << 11) | (buf[i+4] << 3) | ((buf[i+5] >> 5) & 0x07);
- *num = (buf[i+6] & 0x02) + 1;
-
- return fl;
-}
diff --git a/libmpdemux/aac_hdr.h b/libmpdemux/aac_hdr.h
deleted file mode 100644
index be56368925..0000000000
--- a/libmpdemux/aac_hdr.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_AAC_HDR_H
-#define MPLAYER_AAC_HDR_H
-
-#include <stdint.h>
-
-int aac_parse_frame(uint8_t *buf, int *srate, int *num);
-
-#endif /* MPLAYER_AAC_HDR_H */
diff --git a/libmpdemux/demux_aac.c b/libmpdemux/demux_aac.c
deleted file mode 100644
index 9d37d75cf8..0000000000
--- a/libmpdemux/demux_aac.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "parse_es.h"
-#include "stheader.h"
-#include "aac_hdr.h"
-#include "ms_hdr.h"
-
-typedef struct {
- uint8_t *buf;
- uint64_t size; /// amount of time of data packets pushed to demuxer->audio (in bytes)
- float time; /// amount of time elapsed based upon samples_per_frame/sample_rate (in milliseconds)
- float last_pts; /// last pts seen
- int bitrate; /// bitrate computed as size/time
-} aac_priv_t;
-
-static int demux_aac_init(demuxer_t *demuxer)
-{
- aac_priv_t *priv;
-
- priv = calloc(1, sizeof(aac_priv_t));
- if(!priv)
- return 0;
-
- priv->buf = malloc(8);
- if(!priv->buf)
- {
- free(priv);
- return 0;
- }
-
- demuxer->priv = priv;
- return 1;
-}
-
-static void demux_close_aac(demuxer_t *demuxer)
-{
- aac_priv_t *priv = (aac_priv_t *) demuxer->priv;
-
- if(!priv)
- return;
-
- free(priv->buf);
-
- free(demuxer->priv);
-
- return;
-}
-
-/// returns DEMUXER_TYPE_AAC if it finds 8 ADTS frames in 32768 bytes, 0 otherwise
-static int demux_aac_probe(demuxer_t *demuxer)
-{
- int cnt = 0, c, len, srate, num;
- off_t init, probed;
- aac_priv_t *priv;
-
- if(! demux_aac_init(demuxer))
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "COULDN'T INIT aac_demux, exit\n");
- return 0;
- }
-
- priv = (aac_priv_t *) demuxer->priv;
-
- init = probed = stream_tell(demuxer->stream);
- while(probed-init <= 32768 && cnt < 8)
- {
- c = 0;
- while(c != 0xFF)
- {
- c = stream_read_char(demuxer->stream);
- if(c < 0)
- goto fail;
- }
- priv->buf[0] = 0xFF;
- if(stream_read(demuxer->stream, &(priv->buf[1]), 7) < 7)
- goto fail;
-
- len = aac_parse_frame(priv->buf, &srate, &num);
- if(len > 0)
- {
- cnt++;
- stream_skip(demuxer->stream, len - 8);
- }
- probed = stream_tell(demuxer->stream);
- }
-
- stream_seek(demuxer->stream, init);
- if(cnt < 8)
- goto fail;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "demux_aac_probe, INIT: %"PRIu64", PROBED: %"PRIu64", cnt: %d\n", init, probed, cnt);
- return DEMUXER_TYPE_AAC;
-
-fail:
- mp_msg(MSGT_DEMUX, MSGL_V, "demux_aac_probe, failed to detect an AAC stream\n");
- return 0;
-}
-
-static demuxer_t* demux_aac_open(demuxer_t *demuxer)
-{
- sh_audio_t *sh;
-
- sh = new_sh_audio(demuxer, 0);
- sh->ds = demuxer->audio;
- sh->format = mmioFOURCC('M', 'P', '4', 'A');
- demuxer->audio->id = 0;
- demuxer->audio->sh = sh;
-
- demuxer->filepos = stream_tell(demuxer->stream);
-
- return demuxer;
-}
-
-static int demux_aac_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
-{
- aac_priv_t *priv = (aac_priv_t *) demuxer->priv;
- demux_packet_t *dp;
- int c1, c2, len, srate, num;
- float tm = 0;
-
- if(demuxer->stream->eof || (demuxer->movi_end && stream_tell(demuxer->stream) >= demuxer->movi_end))
- return 0;
-
- while(! demuxer->stream->eof)
- {
- c1 = c2 = 0;
- while(c1 != 0xFF)
- {
- c1 = stream_read_char(demuxer->stream);
- if(c1 < 0)
- return 0;
- }
- c2 = stream_read_char(demuxer->stream);
- if(c2 < 0)
- return 0;
- if((c2 & 0xF6) != 0xF0)
- continue;
-
- priv->buf[0] = (unsigned char) c1;
- priv->buf[1] = (unsigned char) c2;
- if(stream_read(demuxer->stream, &(priv->buf[2]), 6) < 6)
- return 0;
-
- len = aac_parse_frame(priv->buf, &srate, &num);
- if(len > 0)
- {
- dp = new_demux_packet(len);
- if(! dp)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "fill_buffer, NEW_ADD_PACKET(%d)FAILED\n", len);
- return 0;
- }
-
-
- memcpy(dp->buffer, priv->buf, 8);
- stream_read(demuxer->stream, &(dp->buffer[8]), len-8);
- if(srate)
- tm = (float) (num * 1024.0/srate);
- priv->last_pts += tm;
- dp->pts = priv->last_pts;
- //fprintf(stderr, "\nPTS: %.3f\n", dp->pts);
- ds_add_packet(demuxer->audio, dp);
- priv->size += len;
- priv->time += tm;
-
- priv->bitrate = (int) (priv->size / priv->time);
- demuxer->filepos = stream_tell(demuxer->stream);
-
- return len;
- }
- else
- stream_skip(demuxer->stream, -6);
- }
-
- return 0;
-}
-
-
-//This is an almost verbatim copy of high_res_mp3_seek(), from demux_audio.c
-static void demux_aac_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags)
-{
- aac_priv_t *priv = (aac_priv_t *) demuxer->priv;
- demux_stream_t *d_audio=demuxer->audio;
- sh_audio_t *sh_audio=d_audio->sh;
- float time;
-
- ds_free_packs(d_audio);
-
- time = (flags & SEEK_ABSOLUTE) ? rel_seek_secs - priv->last_pts : rel_seek_secs;
- if(time < 0)
- {
- stream_seek(demuxer->stream, demuxer->movi_start);
- time = priv->last_pts + time;
- priv->last_pts = 0;
- }
-
- if(time > 0)
- {
- int len, nf, srate, num;
-
- nf = time * sh_audio->samplerate/1024;
-
- while(nf > 0)
- {
- if(stream_read(demuxer->stream,priv->buf, 8) < 8)
- break;
- len = aac_parse_frame(priv->buf, &srate, &num);
- if(len <= 0)
- {
- stream_skip(demuxer->stream, -7);
- continue;
- }
- stream_skip(demuxer->stream, len - 8);
- priv->last_pts += (float) (num*1024.0/srate);
- nf -= num;
- }
- }
-}
-
-
-const demuxer_desc_t demuxer_desc_aac = {
- "AAC demuxer",
- "aac",
- "AAC",
- "Nico Sabbi",
- "Raw AAC files ",
- DEMUXER_TYPE_AAC,
- 0, // unsafe autodetect
- demux_aac_probe,
- demux_aac_fill_buffer,
- demux_aac_open,
- demux_close_aac,
- demux_aac_seek,
- NULL
-};
diff --git a/libmpdemux/demux_avi.c b/libmpdemux/demux_avi.c
index f73648166c..3841cf2736 100644
--- a/libmpdemux/demux_avi.c
+++ b/libmpdemux/demux_avi.c
@@ -29,7 +29,6 @@
#include "stream/stream.h"
#include "demuxer.h"
#include "stheader.h"
-#include "demux_ogg.h"
#include "aviheader.h"
extern const demuxer_desc_t demuxer_desc_avi_ni;
@@ -862,38 +861,6 @@ static int avi_check_file(demuxer_t *demuxer)
}
-static demuxer_t* demux_open_hack_avi(demuxer_t *demuxer)
-{
- struct MPOpts *opts = demuxer->opts;
- sh_audio_t* sh_a;
-
- demuxer = demux_open_avi(demuxer);
- if(!demuxer) return NULL; // failed to open
- sh_a = demuxer->audio->sh;
- if(demuxer->audio->id != -2 && sh_a) {
-#ifdef CONFIG_OGGVORBIS
- // support for Ogg-in-AVI:
- if(sh_a->format == 0xFFFE)
- demuxer = init_avi_with_ogg(demuxer);
- else if(sh_a->format == 0x674F) {
- stream_t* s;
- demuxer_t *od;
- s = new_ds_stream(demuxer->audio);
- od = new_demuxer(opts, s,DEMUXER_TYPE_OGG,-1,-2,-2,NULL);
- if(!demux_ogg_open(od)) {
- mp_tmsg( MSGT_DEMUXER,MSGL_ERR,"Unable to open the Ogg demuxer.\n");
- free_stream(s);
- demuxer->audio->id = -2;
- } else
- demuxer = new_demuxers_demuxer(demuxer,od,demuxer);
- }
-#endif
- }
-
- return demuxer;
-}
-
-
const demuxer_desc_t demuxer_desc_avi = {
"AVI demuxer",
"avi",
@@ -904,7 +871,7 @@ const demuxer_desc_t demuxer_desc_avi = {
1, // safe autodetect
avi_check_file,
demux_avi_fill_buffer,
- demux_open_hack_avi,
+ demux_open_avi,
demux_close_avi,
demux_seek_avi,
demux_avi_control
@@ -920,7 +887,7 @@ const demuxer_desc_t demuxer_desc_avi_ni = {
1, // safe autodetect
avi_check_file,
demux_avi_fill_buffer_ni,
- demux_open_hack_avi,
+ demux_open_avi,
demux_close_avi,
demux_seek_avi,
demux_avi_control
@@ -936,7 +903,7 @@ const demuxer_desc_t demuxer_desc_avi_nini = {
1, // safe autodetect
avi_check_file,
demux_avi_fill_buffer_nini,
- demux_open_hack_avi,
+ demux_open_avi,
demux_close_avi,
demux_seek_avi,
demux_avi_control
diff --git a/libmpdemux/demux_film.c b/libmpdemux/demux_film.c
deleted file mode 100644
index 713c9ea26e..0000000000
--- a/libmpdemux/demux_film.c
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * FILM file parser
- * Copyright (C) 2002 Mike Melanson
- *
- * This demuxer handles FILM (a.k.a. CPK) files commonly found on Sega
- * Saturn CD-ROM games. FILM files have also been found on 3DO games.
- *
- * details of the FILM file format can be found at:
- * http://www.pcisys.net/~melanson/codecs/
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-// chunk types found in a FILM file
-#define CHUNK_FILM mmioFOURCC('F', 'I', 'L', 'M')
-#define CHUNK_FDSC mmioFOURCC('F', 'D', 'S', 'C')
-#define CHUNK_STAB mmioFOURCC('S', 'T', 'A', 'B')
-
-typedef struct film_chunk_t
-{
- off_t chunk_offset;
- int chunk_size;
- unsigned int syncinfo1;
- unsigned int syncinfo2;
-
- float pts;
-} film_chunk_t;
-
-typedef struct film_data_t
-{
- unsigned int total_chunks;
- unsigned int current_chunk;
- film_chunk_t *chunks;
- unsigned int chunks_per_second;
- unsigned int film_version;
-} film_data_t;
-
-static void demux_seek_film(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags)
-{
- film_data_t *film_data = (film_data_t *)demuxer->priv;
- int new_current_chunk=(flags&SEEK_ABSOLUTE)?0:film_data->current_chunk;
-
- if(flags&SEEK_FACTOR)
- new_current_chunk += rel_seek_secs * film_data->total_chunks; // 0..1
- else
- new_current_chunk += rel_seek_secs * film_data->chunks_per_second; // secs
-
-
-mp_msg(MSGT_DECVIDEO, MSGL_INFO,"current, total chunks = %d, %d; seek %5.3f sec, new chunk guess = %d\n",
- film_data->current_chunk, film_data->total_chunks,
- rel_seek_secs, new_current_chunk);
-
- // check if the new chunk number is valid
- if (new_current_chunk < 0)
- new_current_chunk = 0;
- if ((unsigned int)new_current_chunk > film_data->total_chunks)
- new_current_chunk = film_data->total_chunks - 1;
-
- while (((film_data->chunks[new_current_chunk].syncinfo1 == 0xFFFFFFFF) ||
- (film_data->chunks[new_current_chunk].syncinfo1 & 0x80000000)) &&
- (new_current_chunk > 0))
- new_current_chunk--;
-
- film_data->current_chunk = new_current_chunk;
-
-mp_msg(MSGT_DECVIDEO, MSGL_INFO," (flags = %X) actual new chunk = %d (syncinfo1 = %08X)\n",
- flags, film_data->current_chunk, film_data->chunks[film_data->current_chunk].syncinfo1);
- demuxer->video->pts=film_data->chunks[film_data->current_chunk].pts;
-
-}
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_film_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
-{
- int i;
- unsigned char byte_swap;
- int cvid_size;
- sh_video_t *sh_video = demuxer->video->sh;
- sh_audio_t *sh_audio = demuxer->audio->sh;
- film_data_t *film_data = (film_data_t *)demuxer->priv;
- film_chunk_t film_chunk;
- int length_fix_bytes;
- demux_packet_t* dp;
-
- // see if the end has been reached
- if (film_data->current_chunk >= film_data->total_chunks)
- return 0;
-
- film_chunk = film_data->chunks[film_data->current_chunk];
-
- // position stream and fetch chunk
- stream_seek(demuxer->stream, film_chunk.chunk_offset);
-
- // load the chunks manually (instead of using ds_read_packet()), since
- // they require some adjustment
- // (all ones in syncinfo1 indicates an audio chunk)
- if (film_chunk.syncinfo1 == 0xFFFFFFFF)
- {
- if(demuxer->audio->id>=-1){ // audio not disabled
- dp = new_demux_packet(film_chunk.chunk_size);
- if (stream_read(demuxer->stream, dp->buffer, film_chunk.chunk_size) !=
- film_chunk.chunk_size)
- return 0;
- dp->pts = film_chunk.pts;
- dp->pos = film_chunk.chunk_offset;
-
- // adjust the data before queuing it:
- // 8-bit: signed -> unsigned
- // 16-bit: big-endian -> little-endian
- if (sh_audio->wf->wBitsPerSample == 8)
- for (i = 0; i < film_chunk.chunk_size; i++)
- dp->buffer[i] += 128;
- else
- for (i = 0; i < film_chunk.chunk_size; i += 2)
- {
- byte_swap = dp->buffer[i];
- dp->buffer[i] = dp->buffer[i + 1];
- dp->buffer[i + 1] = byte_swap;
- }
-
- /* for SegaSaturn .cpk file, translate audio data if stereo */
- if (sh_audio->wf->nChannels == 2) {
- if (sh_audio->wf->wBitsPerSample == 8) {
- unsigned char* tmp = dp->buffer;
- unsigned char buf[film_chunk.chunk_size];
- for(i = 0; i < film_chunk.chunk_size/2; i++) {
- buf[i*2] = tmp[i];
- buf[i*2+1] = tmp[film_chunk.chunk_size/2+i];
- }
- memcpy( tmp, buf, film_chunk.chunk_size );
- }
- else {/* for 16bit */
- unsigned short *tmp = (unsigned short *)dp->buffer;
- unsigned short buf[film_chunk.chunk_size/2];
- for(i = 0; i < film_chunk.chunk_size/4; i++) {
- buf[i*2] = tmp[i];
- buf[i*2+1] = tmp[film_chunk.chunk_size/4+i];
- }
- memcpy( tmp, buf, film_chunk.chunk_size );
- }
- }
-
- // append packet to DS stream
- ds_add_packet(demuxer->audio, dp);
- }
- }
- else
- {
- // if the demuxer is dealing with CVID data, deal with it a special way
- if (sh_video->format == mmioFOURCC('c', 'v', 'i', 'd'))
- {
- if (film_data->film_version)
- length_fix_bytes = 2;
- else
- length_fix_bytes = 6;
-
- // account for the fix bytes when allocating the buffer
- dp = new_demux_packet(film_chunk.chunk_size - length_fix_bytes);
-
- // these CVID data chunks have a few extra bytes; skip them
- if (stream_read(demuxer->stream, dp->buffer, 10) != 10)
- return 0;
- stream_skip(demuxer->stream, length_fix_bytes);
-
- if (stream_read(demuxer->stream, dp->buffer + 10,
- film_chunk.chunk_size - (10 + length_fix_bytes)) !=
- (film_chunk.chunk_size - (10 + length_fix_bytes)))
- return 0;
-
- dp->pts = film_chunk.pts;
- dp->pos = film_chunk.chunk_offset;
- dp->keyframe = film_chunk.syncinfo1 & 0x80000000;
-
- // fix the CVID chunk size
- cvid_size = film_chunk.chunk_size - length_fix_bytes;
- dp->buffer[1] = (cvid_size >> 16) & 0xFF;
- dp->buffer[2] = (cvid_size >> 8) & 0xFF;
- dp->buffer[3] = (cvid_size >> 0) & 0xFF;
-
- // append packet to DS stream
- ds_add_packet(demuxer->video, dp);
- }
- else
- {
- ds_read_packet(demuxer->video, demuxer->stream, film_chunk.chunk_size,
- film_chunk.pts,
- film_chunk.chunk_offset, (film_chunk.syncinfo1 & 0x80000000) ? 1 : 0);
- }
- }
- film_data->current_chunk++;
-
- return 1;
-}
-
-static demuxer_t* demux_open_film(demuxer_t* demuxer)
-{
- sh_video_t *sh_video = NULL;
- sh_audio_t *sh_audio = NULL;
- film_data_t *film_data;
- film_chunk_t film_chunk;
- int header_size;
- unsigned int chunk_type;
- unsigned int chunk_size;
- unsigned int i;
- unsigned int video_format;
- int audio_channels;
- int counting_chunks;
- unsigned int total_audio_bytes = 0;
-
- film_data = malloc(sizeof(film_data_t));
- film_data->total_chunks = 0;
- film_data->current_chunk = 0;
- film_data->chunks = NULL;
- film_data->chunks_per_second = 0;
-
- // go back to the beginning
- stream_reset(demuxer->stream);
- stream_seek(demuxer->stream, 0);
-
- // read the master chunk type
- chunk_type = stream_read_fourcc(demuxer->stream);
- // validate the chunk type
- if (chunk_type != CHUNK_FILM)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Not a FILM file\n");
- free(film_data);
- return NULL;
- }
-
- // get the header size, which implicitly points past the header and
- // to the start of the data
- header_size = stream_read_dword(demuxer->stream);
- film_data->film_version = stream_read_fourcc(demuxer->stream);
- demuxer->movi_start = header_size;
- demuxer->movi_end = demuxer->stream->end_pos;
- header_size -= 16;
-
- mp_msg(MSGT_DEMUX, MSGL_HINT, "FILM version %.4s\n",
- (char *)&film_data->film_version);
-
- // skip to where the next chunk should be
- stream_skip(demuxer->stream, 4);
-
- // traverse through the header
- while (header_size > 0)
- {
- // fetch the chunk type and size
- chunk_type = stream_read_fourcc(demuxer->stream);
- chunk_size = stream_read_dword(demuxer->stream);
- header_size -= chunk_size;
-
- switch (chunk_type)
- {
- case CHUNK_FDSC:
- mp_msg(MSGT_DECVIDEO, MSGL_V, "parsing FDSC chunk\n");
-
- // fetch the video codec fourcc to see if there's any video
- video_format = stream_read_fourcc(demuxer->stream);
- if (video_format)
- {
- // create and initialize the video stream header
- sh_video = new_sh_video(demuxer, 0);
- demuxer->video->sh = sh_video;
- sh_video->ds = demuxer->video;
-
- sh_video->format = video_format;
- sh_video->disp_h = stream_read_dword(demuxer->stream);
- sh_video->disp_w = stream_read_dword(demuxer->stream);
- mp_msg(MSGT_DECVIDEO, MSGL_V,
- " FILM video: %d x %d\n", sh_video->disp_w,
- sh_video->disp_h);
- }
- else
- // skip height and width if no video
- stream_skip(demuxer->stream, 8);
-
- if(demuxer->audio->id<-1){
- mp_msg(MSGT_DECVIDEO, MSGL_INFO,"chunk size = 0x%X \n",chunk_size);
- stream_skip(demuxer->stream, chunk_size-12-8);
- break; // audio disabled (or no soundcard)
- }
-
- // skip over unknown byte, but only if file had non-NULL version
- if (film_data->film_version)
- stream_skip(demuxer->stream, 1);
-
- // fetch the audio channels to see if there's any audio
- // don't do this if the file is a quirky file with NULL version
- if (film_data->film_version)
- {
- audio_channels = stream_read_char(demuxer->stream);
- if (audio_channels > 0)
- {
- // create and initialize the audio stream header
- sh_audio = new_sh_audio(demuxer, 0);
- demuxer->audio->id = 0;
- demuxer->audio->sh = sh_audio;
- sh_audio->ds = demuxer->audio;
-
- sh_audio->wf = malloc(sizeof(*sh_audio->wf));
-
- // uncompressed PCM format
- sh_audio->wf->wFormatTag = 1;
- sh_audio->format = 1;
- sh_audio->wf->nChannels = audio_channels;
- sh_audio->wf->wBitsPerSample = stream_read_char(demuxer->stream);
- stream_skip(demuxer->stream, 1); // skip unknown byte
- sh_audio->wf->nSamplesPerSec = stream_read_word(demuxer->stream);
- sh_audio->wf->nAvgBytesPerSec =
- sh_audio->wf->nSamplesPerSec * sh_audio->wf->wBitsPerSample
- * sh_audio->wf->nChannels / 8;
- stream_skip(demuxer->stream, 6); // skip the rest of the unknown
-
- mp_msg(MSGT_DECVIDEO, MSGL_V,
- " FILM audio: %d channels, %d bits, %d Hz\n",
- sh_audio->wf->nChannels, 8 * sh_audio->wf->wBitsPerSample,
- sh_audio->wf->nSamplesPerSec);
- }
- else
- stream_skip(demuxer->stream, 10);
- }
- else
- {
- // otherwise, make some assumptions about the audio
-
- // create and initialize the audio stream header
- sh_audio = new_sh_audio(demuxer, 0);
- demuxer->audio->sh = sh_audio;
- sh_audio->ds = demuxer->audio;
-
- sh_audio->wf = malloc(sizeof(*sh_audio->wf));
-
- // uncompressed PCM format
- sh_audio->wf->wFormatTag = 1;
- sh_audio->format = 1;
- sh_audio->wf->nChannels = 1;
- sh_audio->wf->wBitsPerSample = 8;
- sh_audio->wf->nSamplesPerSec = 22050;
- sh_audio->wf->nAvgBytesPerSec =
- sh_audio->wf->nSamplesPerSec * sh_audio->wf->wBitsPerSample
- * sh_audio->wf->nChannels / 8;
-
- mp_msg(MSGT_DECVIDEO, MSGL_V,
- " FILM audio: %d channels, %d bits, %d Hz\n",
- sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample,
- sh_audio->wf->nSamplesPerSec);
- }
- break;
-
- case CHUNK_STAB:
- mp_msg(MSGT_DECVIDEO, MSGL_V, "parsing STAB chunk\n");
-
- if (sh_video)
- {
- sh_video->fps = stream_read_dword(demuxer->stream);
- sh_video->frametime = 1.0 / sh_video->fps;
- }
-
- // fetch the number of chunks
- film_data->total_chunks = stream_read_dword(demuxer->stream);
- film_data->current_chunk = 0;
- mp_msg(MSGT_DECVIDEO, MSGL_V,
- " STAB chunk contains %d chunks\n", film_data->total_chunks);
-
- // allocate enough entries for the chunk
- film_data->chunks =
- calloc(film_data->total_chunks, sizeof(film_chunk_t));
-
- // build the chunk index
- counting_chunks = 1;
- for (i = 0; i < film_data->total_chunks; i++)
- {
- film_chunk = film_data->chunks[i];
- film_chunk.chunk_offset =
- demuxer->movi_start + stream_read_dword(demuxer->stream);
- film_chunk.chunk_size = stream_read_dword(demuxer->stream);
- film_chunk.syncinfo1 = stream_read_dword(demuxer->stream);
- film_chunk.syncinfo2 = stream_read_dword(demuxer->stream);
-
- // count chunks for the purposes of seeking
- if (counting_chunks)
- {
- // if we're counting chunks, always count an audio chunk
- if (film_chunk.syncinfo1 == 0xFFFFFFFF)
- film_data->chunks_per_second++;
- // if it's a video chunk, check if it's time to stop counting
- else if ((film_chunk.syncinfo1 & 0x7FFFFFFF) >= sh_video->fps)
- counting_chunks = 0;
- else
- film_data->chunks_per_second++;
- }
-
- // precalculate PTS
- if (film_chunk.syncinfo1 == 0xFFFFFFFF)
- {
- if(demuxer->audio->id>=-1)
- film_chunk.pts =
- (float)total_audio_bytes / (float)sh_audio->wf->nAvgBytesPerSec;
- total_audio_bytes += film_chunk.chunk_size;
- }
- else
- film_chunk.pts =
- (film_chunk.syncinfo1 & 0x7FFFFFFF) / sh_video->fps;
-
- film_data->chunks[i] = film_chunk;
- }
-
- // in some FILM files (notably '1.09'), the length of the FDSC chunk
- // follows different rules
- if (chunk_size == (film_data->total_chunks * 16))
- header_size -= 16;
- break;
-
- default:
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Unrecognized FILM header chunk: %08X\n",
- chunk_type);
- return NULL;
- break;
- }
- }
-
- demuxer->priv = film_data;
-
- return demuxer;
-}
-
-static void demux_close_film(demuxer_t* demuxer) {
- film_data_t *film_data = demuxer->priv;
-
- if(!film_data)
- return;
- free(film_data->chunks);
- free(film_data);
-
-}
-
-static int film_check_file(demuxer_t* demuxer)
-{
- int signature=stream_read_fourcc(demuxer->stream);
-
- // check for the FILM file magic number
- if(signature==mmioFOURCC('F', 'I', 'L', 'M'))
- return DEMUXER_TYPE_FILM;
-
- return 0;
-}
-
-
-const demuxer_desc_t demuxer_desc_film = {
- "FILM/CPK demuxer for Sega Saturn CD-ROM games",
- "film",
- "FILM",
- "Mike Melanson",
- "",
- DEMUXER_TYPE_FILM,
- 0, // unsafe autodetect (short signature)
- film_check_file,
- demux_film_fill_buffer,
- demux_open_film,
- demux_close_film,
- demux_seek_film,
- NULL
-};
diff --git a/libmpdemux/demux_fli.c b/libmpdemux/demux_fli.c
deleted file mode 100644
index e89fa75d97..0000000000
--- a/libmpdemux/demux_fli.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * FLI file parser
- * copyright (c) 2001 Mike Melanson
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-typedef struct {
- int num_frames;
- int current_frame;
- off_t *filepos;
- unsigned int *frame_size;
-} fli_frames_t;
-
-static void demux_seek_fli(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
- fli_frames_t *frames = (fli_frames_t *)demuxer->priv;
- sh_video_t *sh_video = demuxer->video->sh;
- int newpos=(flags&SEEK_ABSOLUTE)?0:frames->current_frame;
- if(flags&SEEK_FACTOR){
- // float 0..1
- newpos+=rel_seek_secs*frames->num_frames;
- } else {
- // secs
- newpos+=rel_seek_secs*sh_video->fps;
- }
- if(newpos<0) newpos=0; else
- if(newpos>frames->num_frames) newpos=frames->num_frames;
- frames->current_frame=newpos;
-}
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_fli_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds){
- fli_frames_t *frames = (fli_frames_t *)demuxer->priv;
- sh_video_t *sh_video = demuxer->video->sh;
-
- // see if the end has been reached
- if (frames->current_frame >= frames->num_frames)
- return 0;
-
- // fetch the frame from the file
- // first, position the file properly since ds_read_packet() doesn't
- // seem to do it, even though it takes a file offset as a parameter
- stream_seek(demuxer->stream, frames->filepos[frames->current_frame]);
- ds_read_packet(demuxer->video,
- demuxer->stream,
- frames->frame_size[frames->current_frame],
- frames->current_frame/sh_video->fps,
- frames->filepos[frames->current_frame],
- 0 /* what flags? -> demuxer.h (alex) */
- );
-
- // get the next frame ready
- frames->current_frame++;
-
- return 1;
-}
-
-static demuxer_t* demux_open_fli(demuxer_t* demuxer){
- sh_video_t *sh_video = NULL;
- fli_frames_t *frames = malloc(sizeof(fli_frames_t));
- int frame_number;
- int speed;
- unsigned int frame_size;
- int magic_number;
- unsigned char * header;
-
- // go back to the beginning
- stream_reset(demuxer->stream);
- stream_seek(demuxer->stream, 0);
-
- header = calloc(1, sizeof(BITMAPINFOHEADER) + 128);
- stream_read(demuxer->stream, header + sizeof(BITMAPINFOHEADER), 128);
- stream_seek(demuxer->stream, 0);
-
- demuxer->movi_start = 128;
- demuxer->movi_end = stream_read_dword_le(demuxer->stream);
-
- magic_number = stream_read_word_le(demuxer->stream);
-
- if ((magic_number != 0xAF11) && (magic_number != 0xAF12))
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Bad/unknown magic number (%04x)\n",
- magic_number);
- free(header);
- free(frames);
- return NULL;
- }
-
- // fetch the number of frames
- frames->num_frames = stream_read_word_le(demuxer->stream);
- frames->current_frame = 0;
-
- // allocate enough entries for the indices
- // audit: num_frames is 16bit so it is safe against overflow
- frames->filepos = malloc(frames->num_frames * sizeof(off_t));
- frames->frame_size = malloc(frames->num_frames * sizeof(int));
-
- // create a new video stream header
- sh_video = new_sh_video(demuxer, 0);
-
- // make sure the demuxer knows about the new video stream header
- // (even though new_sh_video() ought to take care of it)
- demuxer->video->sh = sh_video;
-
- // make sure that the video demuxer stream header knows about its
- // parent video demuxer stream (this is getting wacky), or else
- // video_read_properties() will choke
- sh_video->ds = demuxer->video;
-
- // custom fourcc for internal MPlayer use
- sh_video->format = mmioFOURCC('F', 'L', 'I', 'C');
-
- sh_video->disp_w = stream_read_word_le(demuxer->stream);
- sh_video->disp_h = stream_read_word_le(demuxer->stream);
-
- // pass extradata to codec
- sh_video->bih = (BITMAPINFOHEADER*)header;
- sh_video->bih->biSize = sizeof(BITMAPINFOHEADER) + 128;
- sh_video->bih->biWidth = sh_video->disp_w;
- sh_video->bih->biHeight = sh_video->disp_h;
-
- // skip the video depth and flags
- stream_skip(demuxer->stream, 4);
-
- // get the speed
- speed = stream_read_word_le(demuxer->stream);
- if (speed == 0)
- speed = 1;
- if (magic_number == 0xAF11)
- speed *= 1000/70;
- sh_video->fps = 1000 / speed;
- sh_video->frametime = 1/sh_video->fps;
-
- // build the frame index
- stream_seek(demuxer->stream, demuxer->movi_start);
- frame_number = 0;
- while ((!stream_eof(demuxer->stream)) && (frame_number < frames->num_frames))
- {
- frames->filepos[frame_number] = stream_tell(demuxer->stream);
- frame_size = stream_read_dword_le(demuxer->stream);
- magic_number = stream_read_word_le(demuxer->stream);
- stream_skip(demuxer->stream, frame_size - 6);
-
- // if this chunk has the right magic number, index it
- if ((magic_number == 0xF1FA) || (magic_number == 0xF5FA))
- {
- frames->frame_size[frame_number] = frame_size;
- frame_number++;
- }
- }
-
- // save the actual number of frames indexed
- frames->num_frames = frame_number;
-
- demuxer->priv = frames;
-
- return demuxer;
-}
-
-static void demux_close_fli(demuxer_t* demuxer) {
- fli_frames_t *frames = demuxer->priv;
-
- if(!frames)
- return;
-
- free(frames->filepos);
- free(frames->frame_size);
- free(frames);
-
-}
-
-
-static int fli_check_file(demuxer_t* demuxer)
-{
- int id;
-
- stream_seek(demuxer->stream, 4);
- id=stream_read_word_le(demuxer->stream);
- // check for the FLI file magic number
- if((id==0xAF11) || (id==0xAF12))
- return DEMUXER_TYPE_FLI;
-
- return 0;
-}
-
-
-const demuxer_desc_t demuxer_desc_fli = {
- "Autodesk FLIC demuxer",
- "fli",
- "FLI",
- "Mike Melanson",
- "Supports also some extensions",
- DEMUXER_TYPE_FLI,
- 0, // unsafe autodetect (short signature)
- fli_check_file,
- demux_fli_fill_buffer,
- demux_open_fli,
- demux_close_fli,
- demux_seek_fli,
- NULL
-};
diff --git a/libmpdemux/demux_lmlm4.c b/libmpdemux/demux_lmlm4.c
deleted file mode 100644
index 739343cdb4..0000000000
--- a/libmpdemux/demux_lmlm4.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * LMLM4 MPEG4 Compression Card stream & file parser
- * Copyright (C) 2003 Maxim Yevtyushkin <max@linuxmedialabs.com>
- * based on SMJPEG file parser by Alex Beregszaszi
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h> /* strtok */
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-typedef struct FrameInfo
-{
- ssize_t frameSize;
- ssize_t paddingSize;
- int frameType;
- int channelNo;
-} FrameInfo;
-
-#define FRAMETYPE_I 0
-#define FRAMETYPE_P 1
-#define FRAMETYPE_B 2
-#define FRAMETYPE_AUDIO_MPEG1L2 4
-#define FRAMETYPE_AUDIO_ULAW 5
-#define FRAMETYPE_AUDIO_ADPCM 6
-
-#define PACKET_BLOCK_SIZE 0x00000200
-#define PACKET_BLOCK_LAST 0x000001FF
-#define PACKET_BLOCK_MASK 0xFFFFFE00
-
-#define MAX_PACKET_SIZE 1048576 // 1 Mb
-
-#define STREAM_START_CODE_SIZE 4
-
-/*
-// codes in MSB first
-static unsigned int start_code [] =
-{
- 0xB0010000, // VISUAL_OBJECT_SEQUENCE_START_CODE
- 0xB6010000, // VOP_START_CODE
- 0x04C4FDFF, // MPEG1LAYERII_START_CODE
- 0x00000000 // end of start codes list
-};
-*/
-
-static int imeHeaderValid(FrameInfo *frame)
-{
- if ( frame->channelNo > 7 ||
- frame->frameSize > MAX_PACKET_SIZE || frame->frameSize <= 0)
- {
- mp_msg(MSGT_DEMUX, MSGL_V,
- "Invalid packet in LMLM4 stream: ch=%d size=%zd\n",
- frame->channelNo, frame->frameSize);
- return 0;
- }
- switch (frame->frameType) {
- case FRAMETYPE_I:
- case FRAMETYPE_P:
- case FRAMETYPE_B:
- case FRAMETYPE_AUDIO_MPEG1L2:
- case FRAMETYPE_AUDIO_ULAW:
- case FRAMETYPE_AUDIO_ADPCM:
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_V, "Invalid packet in LMLM4 stream (wrong packet type %d)\n", frame->frameType);
- return 0;
- }
- return 1;
-}
-
-/*
-int searchMPEG4Stream(demuxer_t* demuxer, IME6400Header *imeHeader)
-{
- void *data;
- ssize_t imeHeaderSize = sizeof(IME6400Header);
- ssize_t dataSize = sizeof(IME6400Header) * 3;
- ssize_t ptr = imeHeaderSize * 2;
- int errNo, startCodeNo;
- off_t pos;
-
- data = malloc(dataSize);
-
- imeHeaderSwap(imeHeader);
- memcpy(data + imeHeaderSize, imeHeader, imeHeaderSize);
-
-// printHex(data + imeHeaderSize, imeHeaderSize);
-
- while ((errNo = stream_read(demuxer->stream, data + imeHeaderSize * 2 , imeHeaderSize)) == imeHeaderSize)
- {
-// printHex(data + imeHeaderSize * 2, imeHeaderSize);
-
- pos = stream_tell(demuxer->stream);
- while (dataSize - ptr >= STREAM_START_CODE_SIZE) {
- startCodeNo = 0;
- while (start_code[startCodeNo])
- {
- if (memcmp(&start_code[startCodeNo], data + ptr, STREAM_START_CODE_SIZE) == 0) // start code match
- {
- memcpy(imeHeader, data + ptr - imeHeaderSize, imeHeaderSize);
- imeHeaderSwap(imeHeader);
- if (imeHeaderValid(imeHeader))
- {
- stream_seek(demuxer->stream, pos - (dataSize - ptr));
- free(data);
- return 0;
- }
- }
- startCodeNo++;
- }
- ptr++;
- }
- memcpy(data,data + imeHeaderSize, imeHeaderSize * 2);
- ptr -= imeHeaderSize;
- }
-
- free(data);
- return errNo;
-}
-*/
-
-static int getFrame(demuxer_t *demuxer, FrameInfo *frameInfo)
-{
- unsigned int packetSize;
-
- frameInfo->channelNo = stream_read_word(demuxer->stream);
- frameInfo->frameType = stream_read_word(demuxer->stream);
- packetSize=stream_read_dword(demuxer->stream);
-
- if(stream_eof(demuxer->stream)){
- frameInfo->frameSize = 0;
- return 0;
- }
-
- frameInfo->frameSize = packetSize - 8; //sizeof(IME6400Header);
- frameInfo->paddingSize = (packetSize & PACKET_BLOCK_LAST) ? PACKET_BLOCK_SIZE - (packetSize & PACKET_BLOCK_LAST) : 0;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "typ: %d chan: %d size: %zd pad: %zd\n",
- frameInfo->frameType,
- frameInfo->channelNo,
- frameInfo->frameSize,
- frameInfo->paddingSize);
-
- if(!imeHeaderValid(frameInfo)){
- // skip this packet
- stream_skip(demuxer->stream,PACKET_BLOCK_SIZE-8);
- frameInfo->frameSize = 0;
- return -1;
- }
-
- return 1;
-}
-
-static int lmlm4_check_file(demuxer_t* demuxer)
-{
- FrameInfo frameInfo;
- unsigned int first;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "Checking for LMLM4 Stream Format\n");
-
- if(getFrame(demuxer, &frameInfo)!=1){
- mp_msg(MSGT_DEMUX, MSGL_V, "LMLM4 Stream Format not found\n");
- return 0;
- }
- first=stream_read_dword(demuxer->stream);
- stream_skip(demuxer->stream,-12);
-
- mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: first=0x%08X\n",first);
-
- switch(frameInfo.frameType){
- case FRAMETYPE_AUDIO_MPEG1L2:
- if( (first & 0xffe00000) != 0xffe00000 ){
- mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: not mpeg audio\n");
- return 0;
- }
- if((4-((first>>17)&3))!=2){
- mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: not layer-2\n");
- return 0;
- }
- if(((first>>10)&0x3)==3){
- mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: invalid audio sampelrate\n");
- return 0;
- }
- mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: first packet is audio, header checks OK!\n");
- break;
- // TODO: add checks for video header too, for case of disabled audio
- }
-
-
-// stream_reset(demuxer->stream);
- mp_msg(MSGT_DEMUX, MSGL_V, "LMLM4 Stream Format found\n");
-
- return DEMUXER_TYPE_LMLM4;
-}
-
-static int video = 0;
-static int frames= 0;
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_lmlm4_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
-{
- FrameInfo frameInfo;
- double pts;
- int id=1;
- int ret;
-
-//hdr:
- demux->filepos = stream_tell(demux->stream);
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "fpos = %"PRId64"\n", (int64_t)demux->filepos);
-
- ret=getFrame(demux, &frameInfo);
- if(ret<=0) return ret; // EOF/error
-
- pts=demux->video->sh ? frames*((sh_video_t*)(demux->video->sh))->frametime : 0;
-
- switch(frameInfo.frameType){
- case FRAMETYPE_AUDIO_MPEG1L2:
- mp_dbg(MSGT_DEMUX, MSGL_DBG2, "Audio Packet\n");
- if (!video)
- {
- stream_skip(demux->stream, frameInfo.frameSize + frameInfo.paddingSize);
- mp_msg(MSGT_DEMUX, MSGL_V, "Skip Audio Packet\n");
- return -1; //goto hdr;
- }
- if(demux->audio->id==-1){
- if(!demux->a_streams[id]) new_sh_audio(demux,id);
- demux->audio->id=id;
- demux->audio->sh=demux->a_streams[id];
- ((sh_audio_t*)(demux->audio->sh))->format=0x50; // mpeg audio layer 1/2
- }
- if(demux->audio->id==id)
- ds_read_packet(demux->audio, demux->stream, frameInfo.frameSize,
- pts, demux->filepos, 0);
- else
- stream_skip(demux->stream,frameInfo.frameSize);
- break;
- case FRAMETYPE_I:
- if (!video) {
- video = 1;
- mp_dbg(MSGT_DEMUX, MSGL_DBG2, "First Video Packet\n");
- }
- case FRAMETYPE_P:
- frames=(frames+1)&(1024*1024-1); // wrap around at 4 hrs to avoid inaccurate float calculations
- if (!video)
- {
- stream_skip(demux->stream, frameInfo.frameSize + frameInfo.paddingSize);
- mp_msg(MSGT_DEMUX, MSGL_V, "Skip Video P Packet\n");
- return -1; //goto hdr;
- }
- mp_dbg(MSGT_DEMUX, MSGL_DBG2, "Video Packet\n");
- if(demux->video->id==-1){
- if(!demux->v_streams[id]) new_sh_video(demux,id);
- demux->video->id=id;
- demux->video->sh=demux->v_streams[id];
- ((sh_video_t*)(demux->video->sh))->format=0x10000004; // mpeg4-ES
- }
- if(demux->video->id==id)
- ds_read_packet(demux->video, demux->stream, frameInfo.frameSize,
- pts, demux->filepos, 0);
- break;
- default:
- stream_skip(demux->stream,frameInfo.frameSize);
- }
-
- stream_skip(demux->stream, frameInfo.paddingSize);
-
- return 1;
-}
-
-static demuxer_t* demux_open_lmlm4(demuxer_t* demuxer){
- sh_audio_t *sh_audio=NULL;
- sh_video_t *sh_video=NULL;
-
-#if 0
- sh_video_t* sh_video;
- sh_audio_t* sh_audio;
- unsigned int htype = 0, hleng;
- int i = 0;
-
- sh_video = new_sh_video(demuxer, 0);
- demuxer->video->sh = sh_video;
- sh_video->ds = demuxer->video;
- sh_video->disp_w = 640;
- sh_video->disp_h = 480;
- sh_video->format = mmioFOURCC('D','I','V','X');
-
- sh_video->bih = calloc(1, sizeof(*sh_video->bih));
-
- /* these are false values */
- sh_video->bih->biSize = 40;
- sh_video->bih->biWidth = sh_video->disp_w;
- sh_video->bih->biHeight = sh_video->disp_h;
- sh_video->bih->biPlanes = 3;
- sh_video->bih->biBitCount = 16;
- sh_video->bih->biCompression = sh_video->format;
- sh_video->bih->biSizeImage = sh_video->disp_w*sh_video->disp_h;
-
- sh_audio = new_sh_audio(demuxer, 0);
- demuxer->audio->sh = sh_audio;
- sh_audio->ds = demuxer->audio;
-
- sh_audio->wf = calloc(1, sizeof(*sh_audio->wf));
-
- sh_audio->samplerate = 48000;
- sh_audio->wf->wBitsPerSample = 16;
- sh_audio->channels = 2;
- sh_audio->format = 0x50;
- sh_audio->wf->wFormatTag = sh_audio->format;
- sh_audio->wf->nChannels = sh_audio->channels;
- sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
- sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nChannels*
- sh_audio->wf->wBitsPerSample*sh_audio->wf->nSamplesPerSec/8;
- sh_audio->wf->nBlockAlign = sh_audio->channels *2;
- sh_audio->wf->cbSize = 0;
-
-#endif
-
- demuxer->seekable = 0;
-
- if(!ds_fill_buffer(demuxer->video)){
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "LMLM4: %s",
- mp_gtext("No video stream found.\n"));
- demuxer->video->sh=NULL;
- } else {
- sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
- }
- if(demuxer->audio->id!=-2) {
- if(!ds_fill_buffer(demuxer->audio)){
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "LMLM4: %s",
- mp_gtext("No audio stream found -> no sound.\n"));
- demuxer->audio->sh=NULL;
- } else {
- sh_audio=demuxer->audio->sh;sh_audio->ds=demuxer->audio;
- }
- }
-
- return demuxer;
-}
-
-static void demux_close_lmlm4(demuxer_t *demuxer)
-{
-// printf("Close LMLM4 Stream\n");
- return;
-}
-
-
-const demuxer_desc_t demuxer_desc_lmlm4 = {
- "LMLM4 MPEG4 Compression Card stream demuxer",
- "lmlm4",
- "RAW LMLM4",
- "Maxim Yevtyushkin",
- "",
- DEMUXER_TYPE_LMLM4,
- 0, // unsafe autodetect
- lmlm4_check_file,
- demux_lmlm4_fill_buffer,
- demux_open_lmlm4,
- demux_close_lmlm4,
- NULL,
- NULL
-};
diff --git a/libmpdemux/demux_mov.c b/libmpdemux/demux_mov.c
deleted file mode 100644
index 96fb1a2d86..0000000000
--- a/libmpdemux/demux_mov.c
+++ /dev/null
@@ -1,2350 +0,0 @@
-/*
- * QuickTime MOV file parser
- * copyright(c) 2001 A'rpi
- * additional work by Atmos
- * based on TOOLS/movinfo.c by A'rpi & Al3x
- * compressed header support from moov.c of the openquicktime lib.
- *
- * references: http://openquicktime.sf.net/, http://www.heroinewarrior.com/
- * http://www.geocities.com/SiliconValley/Lakes/2160/fformats/files/mov.pdf
- * (above URL no longer works, file mirrored somewhere? ::atmos)
- * The QuickTime File Format PDF from Apple:
- * http://developer.apple.com/techpubs/quicktime/qtdevdocs/PDF/QTFileFormat.pdf
- * (Complete list of documentation at http://developer.apple.com/quicktime/)
- * MP4-Lib sources from http://mpeg4ip.sf.net/ might be useful for .mp4
- * as well as .mov specific stuff.
- *
- * All sort of Stuff about MPEG4:
- * http://www.cmlab.csie.ntu.edu.tw/~pkhsiao/thesis.html
- * I really recommend N4270-1.doc and N4270-2.doc which are exact specs
- * of the MP4-File Format and the MPEG4 Specific extensions. ::atmos
- * TSGS#15(02)0088
- * http://www.3gpp.org/ftp/tsg_sa/TSG_SA/TSGS_15/Docs/pdf/SP-020088.pdf
- * http://www.3gpp2.org/Public_html/specs/C.S0050-0_v1.0_121503.pdf
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <inttypes.h>
-
-#include <libavutil/common.h>
-#include <libavutil/intreadwrite.h>
-
-#include "config.h"
-
-#ifdef CONFIG_QUICKTIME
-#include <QuickTime/QuickTime.h>
-#include <QuickTime/ImageCompression.h>
-#include <QuickTime/ImageCodec.h>
-#else
-#include "loader/qtx/qtxsdk/components.h"
-#endif
-
-#if CONFIG_ZLIB
-#include <zlib.h>
-#endif
-
-#ifndef _FCNTL_H
-#include <fcntl.h>
-#endif
-
-#include "mp_msg.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-#include "libmpcodecs/img_format.h"
-
-#include "sub/sub.h"
-
-#include "demux_mov.h"
-#include "qtpalette.h"
-#include "parse_mp4.h" // .MP4 specific stuff
-
-#define char2short(x,y) AV_RB16(&(x)[(y)])
-#define char2int(x,y) AV_RB32(&(x)[(y)])
-
-typedef struct {
- unsigned int pts; // duration
- unsigned int size;
- off_t pos;
-} mov_sample_t;
-
-typedef struct {
- unsigned int sample; // number of the first sample in the chunk
- unsigned int size; // number of samples in the chunk
- int desc; // for multiple codecs mode - not used
- off_t pos;
-} mov_chunk_t;
-
-typedef struct {
- unsigned int first;
- unsigned int spc;
- unsigned int sdid;
-} mov_chunkmap_t;
-
-typedef struct {
- unsigned int num;
- unsigned int dur;
-} mov_durmap_t;
-
-typedef struct {
- unsigned int dur;
- unsigned int pos;
- int speed;
- //
- int frames;
- int start_sample;
- int start_frame;
- int pts_offset;
-} mov_editlist_t;
-
-#define MOV_TRAK_UNKNOWN 0
-#define MOV_TRAK_VIDEO 1
-#define MOV_TRAK_AUDIO 2
-#define MOV_TRAK_FLASH 3
-#define MOV_TRAK_GENERIC 4
-#define MOV_TRAK_CODE 5
-
-typedef struct {
- int id;
- int type;
- off_t pos;
- //
- unsigned int media_handler;
- unsigned int data_handler;
- //
- int timescale;
- unsigned int length;
- int samplesize; // 0 = variable
- int duration; // 0 = variable
- int width,height; // for video
- unsigned int fourcc;
- unsigned int nchannels;
- unsigned int samplebytes;
- //
- int tkdata_len; // track data
- unsigned char* tkdata;
- int stdata_len; // stream data
- unsigned char* stdata;
- //
- unsigned char* stream_header;
- int stream_header_len; // if >0, this header should be sent before the 1st frame
- //
- int samples_size;
- mov_sample_t* samples;
- int chunks_size;
- mov_chunk_t* chunks;
- int chunkmap_size;
- mov_chunkmap_t* chunkmap;
- int durmap_size;
- mov_durmap_t* durmap;
- int keyframes_size;
- unsigned int* keyframes;
- int editlist_size;
- mov_editlist_t* editlist;
- int editlist_pos;
- //
- void* desc; // image/sound/etc description (pointer to ImageDescription etc)
-} mov_track_t;
-
-static void mov_build_index(mov_track_t* trak,int timescale){
- int i,j,s;
- int last=trak->chunks_size;
- unsigned int pts=0;
-
-#if 0
- if (trak->chunks_size <= 0)
- {
- mp_msg(MSGT_DEMUX, MSGL_WARN, "No chunk offset table, trying to build one!\n");
-
- trak->chunks_size = trak->samples_size; /* XXX: FIXME ! */
- // audit: this code will be vulnerable if it is reenabled (currently #if 0)
- trak->chunks = realloc(trak->chunks, sizeof(mov_chunk_t)*trak->chunks_size);
-
- for (i=0; i < trak->chunks_size; i++)
- trak->chunks[i].pos = -1;
- }
-#endif
-
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV track #%d: %d chunks, %d samples\n",trak->id,trak->chunks_size,trak->samples_size);
- mp_msg(MSGT_DEMUX, MSGL_V, "pts=%d scale=%d time=%5.3f\n",trak->length,trak->timescale,(float)trak->length/(float)trak->timescale);
-
- // process chunkmap:
- i=trak->chunkmap_size;
- while(i>0){
- --i;
- j=trak->chunkmap[i].first;
- for(;j>=0 && j<last;j++){
- trak->chunks[j].desc=trak->chunkmap[i].sdid;
- trak->chunks[j].size=trak->chunkmap[i].spc;
- }
- last=FFMIN(trak->chunkmap[i].first, trak->chunks_size);
- }
-
-#if 0
- for (i=0; i < trak->chunks_size; i++)
- {
- /* fixup position */
- if (trak->chunks[i].pos == -1)
- if (i > 0)
- trak->chunks[i].pos = trak->chunks[i-1].pos + trak->chunks[i-1].size;
- else
- trak->chunks[i].pos = 0; /* FIXME: set initial pos */
-#endif
-
- // calc pts of chunks:
- s=0;
- for(j=0;j<trak->chunks_size;j++){
- trak->chunks[j].sample=s;
- s+=trak->chunks[j].size;
- }
- i = 0;
- for (j = 0; j < trak->durmap_size; j++)
- i += trak->durmap[j].num;
- if (i != s) {
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- "MOV: durmap and chunkmap sample count differ (%i vs %i)\n", i, s);
- if (i > s) s = i;
- }
-
- // workaround for fixed-size video frames (dv and uncompressed)
- if(!trak->samples_size && trak->type!=MOV_TRAK_AUDIO){
- trak->samples=calloc(s, sizeof(mov_sample_t));
- trak->samples_size=trak->samples ? s : 0;
- for(i=0;i<trak->samples_size;i++)
- trak->samples[i].size=trak->samplesize;
- trak->samplesize=0;
- }
-
- if(!trak->samples_size){
- // constant sampesize
- if(trak->durmap_size==1 || (trak->durmap_size==2 && trak->durmap[1].num==1)){
- trak->duration=trak->durmap[0].dur;
- } else mp_msg(MSGT_DEMUX, MSGL_ERR, "*** constant samplesize & variable duration not yet supported! ***\nContact the author if you have such sample file!\n");
- return;
- }
-
- if (trak->samples_size < s) {
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- "MOV: durmap or chunkmap bigger than sample count (%i vs %i)\n",
- s, trak->samples_size);
- free(trak->samples);
- trak->samples = calloc(s, sizeof(mov_sample_t));
- trak->samples_size = trak->samples ? s : 0;
- }
-
- // calc pts:
- s=0;
- for(j=0;j<trak->durmap_size;j++){
- for(i=0;i<trak->durmap[j].num;i++){
- if (s >= trak->samples_size)
- break;
- trak->samples[s].pts=pts;
- ++s;
- pts+=trak->durmap[j].dur;
- }
- }
-
- // calc sample offsets
- s=0;
- for(j=0;j<trak->chunks_size;j++){
- off_t pos=trak->chunks[j].pos;
- for(i=0;i<trak->chunks[j].size;i++){
- if (s >= trak->samples_size)
- break;
- trak->samples[s].pos=pos;
- mp_msg(MSGT_DEMUX, MSGL_DBG3, "Sample %5d: pts=%8d off=0x%08X size=%d\n",s,
- trak->samples[s].pts,
- (int)trak->samples[s].pos,
- trak->samples[s].size);
- pos+=trak->samples[s].size;
- ++s;
- }
- }
-
- // precalc editlist entries
- if(trak->editlist_size>0){
- int frame=0;
- int e_pts=0;
- for(i=0;i<trak->editlist_size;i++){
- mov_editlist_t* el=&trak->editlist[i];
- int sample=0;
- int pts=el->pos;
- el->start_frame=frame;
- if(pts<0){
- // skip!
- el->frames=0; continue;
- }
- // find start sample
- for(;sample<trak->samples_size;sample++){
- if(pts<=trak->samples[sample].pts) break;
- }
- el->start_sample=sample;
- el->pts_offset=((long long)e_pts*(long long)trak->timescale)/(long long)timescale-trak->samples[sample].pts;
- pts+=((long long)el->dur*(long long)trak->timescale)/(long long)timescale;
- e_pts+=el->dur;
- // find end sample
- for(;sample<trak->samples_size;sample++){
- if(pts<trak->samples[sample].pts) break;
- }
- el->frames=sample-el->start_sample;
- frame+=el->frames;
- mp_msg(MSGT_DEMUX,MSGL_V,"EL#%d: pts=%d 1st_sample=%d frames=%d (%5.3fs) pts_offs=%d\n",i,
- el->pos,el->start_sample, el->frames,
- (float)(el->dur)/(float)timescale, el->pts_offset);
- }
- }
-
-}
-
-#define MOV_MAX_TRACKS 256
-#define MOV_MAX_SUBLEN 1024
-
-typedef struct {
- off_t moov_start;
- off_t moov_end;
- off_t mdat_start;
- off_t mdat_end;
- int track_db;
- mov_track_t* tracks[MOV_MAX_TRACKS];
- int timescale; // movie timescale
- int duration; // movie duration (in movie timescale units)
- subtitle subs;
- char subtext[MOV_MAX_SUBLEN + 1];
- int current_sub;
-} mov_priv_t;
-
-#define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d))
-
-static int mov_check_file(demuxer_t* demuxer){
- int flags=0;
- int no=0;
- mov_priv_t* priv=calloc(1, sizeof(mov_priv_t));
-
- mp_msg(MSGT_DEMUX,MSGL_V,"Checking for MOV\n");
-
- priv->current_sub = -1;
-
- while(1){
- int i;
- int skipped=8;
- off_t len=stream_read_dword(demuxer->stream);
- unsigned int id=stream_read_dword(demuxer->stream);
- if(stream_eof(demuxer->stream)) break; // EOF
- if (len == 1) /* real size is 64bits - cjb */
- {
-#ifndef _LARGEFILE_SOURCE
- if (stream_read_dword(demuxer->stream) != 0)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "64bit file, but you've compiled MPlayer without LARGEFILE support!\n");
- len = stream_read_dword(demuxer->stream);
-#else
- len = stream_read_qword(demuxer->stream);
-#endif
- skipped += 8;
- }
-#if 0
- else if (len == 0) /* deleted chunk */
- {
- /* XXX: CJB! is this right? - alex */
- goto skip_chunk;
- }
-#endif
- if(len<8) break; // invalid chunk
-
- switch(id){
- case MOV_FOURCC('f','t','y','p'): {
- unsigned int tmp;
- // File Type Box (ftyp):
- // char[4] major_brand (eg. 'isom')
- // int minor_version (eg. 0x00000000)
- // char[4] compatible_brands[] (eg. 'mp41')
- // compatible_brands list spans to the end of box
-#if 1
- tmp = stream_read_dword(demuxer->stream);
- switch(tmp) {
- case MOV_FOURCC('i','s','o','m'):
- mp_msg(MSGT_DEMUX,MSGL_V,"ISO: File Type Major Brand: ISO Base Media\n");
- break;
- case MOV_FOURCC('m','p','4','1'):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v1\n");
- break;
- case MOV_FOURCC('m','p','4','2'):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v2\n");
- break;
- case MOV_FOURCC('M','4','A',' '):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Apple iTunes AAC-LC Audio\n");
- break;
- case MOV_FOURCC('M','4','P',' '):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Apple iTunes AAC-LC Protected Audio\n");
- break;
- case MOV_FOURCC('q','t',' ',' '):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Original QuickTime\n");
- break;
- case MOV_FOURCC('3','g','p','1'):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 1\n");
- break;
- case MOV_FOURCC('3','g','p','2'):
- case MOV_FOURCC('3','g','2','a'):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 2\n");
- break;
- case MOV_FOURCC('3','g','p','3'):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 3\n");
- break;
- case MOV_FOURCC('3','g','p','4'):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 4\n");
- break;
- case MOV_FOURCC('3','g','p','5'):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 5\n");
- break;
- case MOV_FOURCC('m','m','p','4'):
- mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Mobile ISO/IEC 14496-1 (MPEG-4 system)\n");
- break;
- default:
- tmp = be2me_32(tmp);
- mp_msg(MSGT_DEMUX,MSGL_WARN,"ISO: Unknown File Type Major Brand: %.4s\n",(char *)&tmp);
- }
- mp_msg(MSGT_DEMUX,MSGL_V,"ISO: File Type Minor Version: %d\n",
- stream_read_dword(demuxer->stream));
- skipped += 8;
- // List all compatible brands
- for(i = 0; i < ((len-16)/4); i++) {
- tmp = be2me_32(stream_read_dword(demuxer->stream));
- mp_msg(MSGT_DEMUX,MSGL_V,"ISO: File Type Compatible Brand #%d: %.4s\n",i,(char *)&tmp);
- skipped += 4;
- }
-#endif
- } break;
- case MOV_FOURCC('m','o','o','v'):
-// case MOV_FOURCC('c','m','o','v'):
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie header found!\n");
- priv->moov_start=(off_t)stream_tell(demuxer->stream);
- priv->moov_end=(off_t)priv->moov_start+len-skipped;
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"MOV: Movie header: start: %"PRIx64" end: %"PRIx64"\n",
- (int64_t)priv->moov_start, (int64_t)priv->moov_end);
- skipped+=8;
- i = stream_read_dword(demuxer->stream)-8;
- if(stream_read_dword(demuxer->stream)==MOV_FOURCC('r','m','r','a')){
- skipped+=i;
- mp_msg(MSGT_DEMUX,MSGL_INFO,"MOV: Reference Media file!!!\n");
- //set demuxer type to playlist ...
- demuxer->type=DEMUXER_TYPE_PLAYLIST;
- while(i>0){
- int len=stream_read_dword(demuxer->stream)-8;
- int fcc=stream_read_dword(demuxer->stream);
- if(len<0) break; // EOF!?
- i-=8;
-// printf("i=%d len=%d\n",i,len);
- switch(fcc){
- case MOV_FOURCC('r','m','d','a'):
- continue;
- case MOV_FOURCC('r','d','r','f'): {
- av_unused int tmp=stream_read_dword(demuxer->stream);
- av_unused int type=stream_read_dword_le(demuxer->stream);
- int slen=stream_read_dword(demuxer->stream);
- //char* s=malloc(slen+1);
- //stream_read(demuxer->stream,s,slen);
-
- //FIXME: also store type & data_rate ?
- ds_read_packet(demuxer->video,
- demuxer->stream,
- slen,
- 0,
- stream_tell(demuxer->stream),
- 0 // no flags
- );
- flags|=4;
- mp_msg(MSGT_DEMUX,MSGL_V,"Added reference to playlist\n");
- //s[slen]=0;
- //mp_msg(MSGT_DEMUX,MSGL_INFO,"REF: [%.4s] %s\n",&type,s);
- len-=12+slen;i-=12+slen; break;
- }
- case MOV_FOURCC('r','m','d','r'): {
- av_unused int flags=stream_read_dword(demuxer->stream);
- int rate=stream_read_dword(demuxer->stream);
- mp_msg(MSGT_DEMUX,MSGL_V," min. data rate: %d bits/sec\n",rate);
- len-=8; i-=8; break;
- }
- case MOV_FOURCC('r','m','q','u'): {
- int q=stream_read_dword(demuxer->stream);
- mp_msg(MSGT_DEMUX,MSGL_V," quality index: %d\n",q);
- len-=4; i-=4; break;
- }
- }
- i-=len;stream_skip(demuxer->stream,len);
- }
- }
- flags|=1;
- break;
- case MOV_FOURCC('w','i','d','e'):
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: 'WIDE' chunk found!\n");
- if(flags&2) break;
- case MOV_FOURCC('m','d','a','t'):
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie DATA found!\n");
- priv->mdat_start=stream_tell(demuxer->stream);
- priv->mdat_end=priv->mdat_start+len-skipped;
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"MOV: Movie data: start: %"PRIx64" end: %"PRIx64"\n",
- (int64_t)priv->mdat_start, (int64_t)priv->mdat_end);
- flags|=2;
- if(flags==3){
- // if we're over the headers, then we can stop parsing here!
- demuxer->priv=priv;
- return DEMUXER_TYPE_MOV;
- }
- break;
- case MOV_FOURCC('f','r','e','e'):
- case MOV_FOURCC('s','k','i','p'):
- case MOV_FOURCC('j','u','n','k'):
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"MOV: free space (len: %"PRId64")\n", (int64_t)len);
- /* unused, if you edit a mov, you can use space provided by free atoms (redefining it) */
- break;
- case MOV_FOURCC('p','n','o','t'):
- case MOV_FOURCC('P','I','C','T'):
- /* dunno what, but we shoudl ignore it */
- break;
- default:
- if(no==0){ free(priv); return 0;} // first chunk is bad!
- id = be2me_32(id);
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len);
- }
-//skip_chunk:
- if(!stream_skip(demuxer->stream,len-skipped)) break;
- ++no;
- }
-
- if(flags==3){
- demuxer->priv=priv;
- return DEMUXER_TYPE_MOV;
- }
- free(priv);
-
- if ((flags==5) || (flags==7)) // reference & header sent
- return DEMUXER_TYPE_PLAYLIST;
-
- if(flags==1)
- mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing data (mdat) chunk! Maybe broken file...\n");
- else if(flags==2)
- mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing header (moov/cmov) chunk! Maybe broken file...\n");
-
- return 0;
-}
-
-static void demux_close_mov(demuxer_t *demuxer) {
- mov_priv_t* priv = demuxer->priv;
- int i;
- if (!priv)
- return;
- for (i = 0; i < MOV_MAX_TRACKS; i++) {
- mov_track_t *track = priv->tracks[i];
- if (track) {
- free(track->tkdata);
- free(track->stdata);
- free(track->stream_header);
- free(track->samples);
- free(track->chunks);
- free(track->chunkmap);
- free(track->durmap);
- free(track->keyframes);
- free(track->editlist);
- free(track->desc);
- free(track);
- }
- }
- free(priv);
-}
-
-unsigned int store_ughvlc(unsigned char *s, unsigned int v){
- unsigned int n = 0;
-
- while(v >= 0xff) {
- *s++ = 0xff;
- v -= 0xff;
- n++;
- }
- *s = v;
- n++;
-
- return n;
-}
-
-static void init_vobsub(sh_sub_t *sh, mov_track_t *trak) {
- sh->type = 'v';
- if (trak->stdata_len < 106)
- return;
- sh->extradata_len = 16*4;
- sh->extradata = malloc(sh->extradata_len);
- memcpy(sh->extradata, trak->stdata + 42, sh->extradata_len);
-}
-
-static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id,
- off_t pos, off_t len, mov_track_t* trak);
-
-static int gen_sh_audio(sh_audio_t* sh, mov_track_t* trak, int timescale) {
-#if 0
- struct {
- int16_t version; // 0 or 1 (version 1 is qt3.0+)
- int16_t revision; // 0
- int32_t vendor_id; // 0
- int16_t channels; // 1 or 2 (Mono/Stereo)
- int16_t samplesize; // 8 or 16 (8Bit/16Bit)
- int16_t compression_id; // if version 0 then 0
- // if version 1 and vbr then -2 else 0
- int16_t packet_size; // 0
- uint16_t sample_rate; // samplerate (Hz)
- // qt3.0+ (version == 1)
- uint32_t samples_per_packet; // 0 or num uncompressed samples in a packet
- // if 0 below three values are also 0
- uint32_t bytes_per_packet; // 0 or num compressed bytes for one channel
- uint32_t bytes_per_frame; // 0 or num compressed bytes for all channels
- // (channels * bytes_per_packet)
- uint32_t bytes_per_sample; // 0 or size of uncompressed sample
- // if samples_per_packet and bytes_per_packet are constant (CBR)
- // then bytes_per_frame and bytes_per_sample must be 0 (else is VBR)
- // ---
- // optional additional atom-based fields
- // ([int32_t size,int32_t type,some data ],repeat)
- } my_stdata;
-#endif
- int version = -1, adjust;
- int is_vorbis = 0;
- sh->format=trak->fourcc;
-
- // crude audio delay from editlist0 hack ::atm
- if(trak->editlist_size>=1) {
- if(trak->editlist[0].pos == -1) {
- sh->stream_delay = (float)trak->editlist[0].dur/(float)timescale;
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay);
- }
- }
-
-
- switch( sh->format ) {
- case 0x726D6173: /* samr */
- /* amr narrowband */
- trak->samplebytes=sh->samplesize=1;
- trak->nchannels=sh->channels=1;
- sh->samplerate=8000;
- break;
-
- case 0x62776173: /* sawb */
- /* amr wideband */
- trak->samplebytes=sh->samplesize=1;
- trak->nchannels=sh->channels=1;
- sh->samplerate=16000;
- break;
-
- default:
-
-// assumptions for below table: short is 16bit, int is 32bit, intfp is 16bit
-// XXX: 32bit fixed point numbers (intfp) are only 2 Byte!
-// short values are usually one byte leftpadded by zero
-// int values are usually two byte leftpadded by zero
-// stdata[]:
-// 8 short version
-// 10 short revision
-// 12 int vendor_id
-// 16 short channels
-// 18 short samplesize
-// 20 short compression_id
-// 22 short packet_size (==0)
-// 24 intfp sample_rate
-// (26 short) unknown (==0)
-// ---- qt3.0+ (version>=1)
-// 28 int samples_per_packet
-// 32 int bytes_per_packet
-// 36 int bytes_per_frame
-// 40 int bytes_per_sample
-// there may be additional atoms following at 28 (version 0)
-// or 44 (version 1), eg. esds atom of .MP4 files
-// esds atom:
-// 28 int atom size (bytes of int size, int type and data)
-// 32 char[4] atom type (fourc charater code -> esds)
-// 36 char[] atom data (len=size-8)
-
-// TODO: fix parsing for files using version 2.
- if (trak->stdata_len < 26) {
- mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: broken (too small) sound atom!\n");
- return 0;
- }
- version=char2short(trak->stdata,8);
- if (version > 1)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: version %d sound atom may not parse correctly!\n", version);
- trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8;
-
- /* I can't find documentation, but so far this is the case. -Corey */
- switch (char2short(trak->stdata,16)) {
- case 1:
- trak->nchannels = 1; break;
- case 2:
- trak->nchannels = 2; break;
- case 3:
- trak->nchannels = 6; break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- "MOV: unable to determine audio channels, assuming 2 (got %d)\n",
- char2short(trak->stdata,16));
- trak->nchannels = 2;
- }
- sh->channels = trak->nchannels;
-
- /*printf("MOV: timescale: %d samplerate: %d durmap: %d (%d) -> %d (%d)\n",
- trak->timescale, char2short(trak->stdata,24), trak->durmap[0].dur,
- trak->durmap[0].num, trak->timescale/trak->durmap[0].dur,
- char2short(trak->stdata,24)/trak->durmap[0].dur);*/
- sh->samplerate=char2short(trak->stdata,24);
- if((sh->samplerate < 7000) && trak->durmap && trak->durmap[0].dur > 1) {
- switch(char2short(trak->stdata,24)/trak->durmap[0].dur) {
- // TODO: add more cases.
- case 31:
- sh->samplerate = 32000; break;
- case 43:
- sh->samplerate = 44100; break;
- case 47:
- sh->samplerate = 48000; break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- "MOV: unable to determine audio samplerate, "
- "assuming 44.1kHz (got %d)\n",
- char2short(trak->stdata,24)/trak->durmap[0].dur);
- sh->samplerate = 44100;
- }
- }
- }
- mp_msg(MSGT_DEMUX, MSGL_V, "Audio bits: %d chans: %d rate: %d\n",
- sh->samplesize*8,sh->channels,sh->samplerate);
-
- if(trak->stdata_len >= 44 && trak->stdata[9]>=1){
- mp_msg(MSGT_DEMUX,MSGL_V,"Audio header: samp/pack=%d bytes/pack=%d bytes/frame=%d bytes/samp=%d \n",
- char2int(trak->stdata,28),
- char2int(trak->stdata,32),
- char2int(trak->stdata,36),
- char2int(trak->stdata,40));
- if(trak->stdata_len>=44+8){
- int len=char2int(trak->stdata,44);
- int fcc=char2int(trak->stdata,48);
- // we have extra audio headers!!!
- mp_msg(MSGT_DEMUX,MSGL_V,"Audio extra header: len=%d fcc=0x%X\n",len,fcc);
- if((len >= 4) &&
- (char2int(trak->stdata,52) >= 12) &&
- (char2int(trak->stdata,52+4) == MOV_FOURCC('f','r','m','a'))) {
- switch(char2int(trak->stdata,52+8)) {
- case MOV_FOURCC('a','l','a','c'):
- if (len >= 36 + char2int(trak->stdata,52)) {
- sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52));
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found alac atom (%d)!\n", sh->codecdata_len);
- sh->codecdata = malloc(sh->codecdata_len);
- memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len);
- }
- break;
- case MOV_FOURCC('i','n','2','4'):
- case MOV_FOURCC('i','n','3','2'):
- case MOV_FOURCC('f','l','3','2'):
- case MOV_FOURCC('f','l','6','4'):
- if ((len >= 22) &&
- (char2int(trak->stdata,52+16)==MOV_FOURCC('e','n','d','a')) &&
- (char2short(trak->stdata,52+20))) {
- sh->format=char2int(trak->stdata,52+8);
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found little endian PCM data, reversed fourcc:%04x\n", sh->format);
- }
- break;
- default:
- if (len > 8 && len + 44 <= trak->stdata_len) {
- sh->codecdata_len = len-8;
- sh->codecdata = malloc(sh->codecdata_len);
- memcpy(sh->codecdata, trak->stdata+44+8, sh->codecdata_len);
- }
- }
- } else {
- if (len > 8 && len + 44 <= trak->stdata_len) {
- sh->codecdata_len = len-8;
- sh->codecdata = malloc(sh->codecdata_len);
- memcpy(sh->codecdata, trak->stdata+44+8, sh->codecdata_len);
- }
- }
- }
- }
-
- switch (version) {
- case 0:
- adjust = 0; break;
- case 1:
- adjust = 48; break;
- case 2:
- adjust = 68; break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: unknown sound atom version (%d); may not work!\n", version);
- adjust = 68;
- }
- if (trak->stdata_len >= 36 + adjust) {
- int atom_len = char2int(trak->stdata,28+adjust);
- if (atom_len < 0 || atom_len > trak->stdata_len - 28 - adjust) atom_len = trak->stdata_len - 28 - adjust;
- switch(char2int(trak->stdata,32+adjust)) { // atom type
- case MOV_FOURCC('e','s','d','s'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len);
- if(atom_len > 8) {
- esds_t esds;
- if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) {
- /* 0xdd is a "user private" id, not an official allocated id (see http://www.mp4ra.org/object.html),
- so perform some extra checks to be sure that this is really vorbis audio */
- if(esds.objectTypeId==0xdd && esds.streamType==0x15 && sh->format==0x6134706D && esds.decoderConfigLen > 8)
- {
- //vorbis audio
- unsigned char *buf[3];
- unsigned short sizes[3];
- int offset, len, k;
- unsigned char *ptr = esds.decoderConfig;
-
- if(ptr[0] != 0 || ptr[1] != 30) goto quit_vorbis_block; //wrong extradata layout
-
- offset = len = 0;
- for(k = 0; k < 3; k++)
- {
- sizes[k] = (ptr[offset]<<8) | ptr[offset+1];
- len += sizes[k];
- offset += 2;
- if(offset + sizes[k] > esds.decoderConfigLen)
- {
- mp_msg(MSGT_DEMUX, MSGL_FATAL, "MOV: ERROR!, not enough vorbis extradata to read: offset = %d, k=%d, size=%d, len: %d\n", offset, k, sizes[k], esds.decoderConfigLen);
- goto quit_vorbis_block;
- }
- buf[k] = malloc(sizes[k]);
- if(!buf[k]) goto quit_vorbis_block;
- memcpy(buf[k], &ptr[offset], sizes[k]);
- offset += sizes[k];
- }
-
- sh->codecdata_len = len + len/255 + 64;
- sh->codecdata = malloc(sh->codecdata_len);
- ptr = sh->codecdata;
-
- ptr[0] = 2;
- offset = 1;
- offset += store_ughvlc(&ptr[offset], sizes[0]);
- offset += store_ughvlc(&ptr[offset], sizes[1]);
- for(k = 0; k < 3; k++)
- {
- memcpy(&ptr[offset], buf[k], sizes[k]);
- offset += sizes[k];
- }
-
- sh->codecdata_len = offset;
- sh->codecdata = realloc(sh->codecdata, offset);
- mp_msg(MSGT_DEMUX,MSGL_V, "demux_mov, vorbis extradata size: %d\n", offset);
- is_vorbis = 1;
-quit_vorbis_block:
- sh->format = mmioFOURCC('v', 'r', 'b', 's');
- }
- sh->i_bps = esds.avgBitrate/8;
-
-// printf("######## audio format = %d ########\n",esds.objectTypeId);
- if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3)
- sh->format=0x55; // .mp3
-
- if(esds.objectTypeId==MP4OTI_13kVoice) { // 13K Voice, defined by 3GPP2
- sh->format=mmioFOURCC('Q', 'c', 'l', 'p');
- trak->nchannels=sh->channels=1;
- trak->samplebytes=sh->samplesize=1;
- }
-
- // dump away the codec specific configuration for the AAC decoder
- if(esds.decoderConfigLen){
- if( (esds.decoderConfig[0]>>3) == 29 )
- sh->format = 0x1d61346d; // request multi-channel mp3 decoder
- if(!is_vorbis)
- {
- sh->codecdata_len = esds.decoderConfigLen;
- sh->codecdata = malloc(sh->codecdata_len);
- memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len);
- }
- }
- }
- mp4_free_esds(&esds); // freeup esds mem
-#if 0
- { FILE* f=fopen("esds.dat","wb");
- fwrite(&trak->stdata[36],atom_len-8,1,f);
- fclose(f); }
-#endif
- }
- } break;
- case MOV_FOURCC('a','l','a','c'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found alac atom (%d)!\n", atom_len);
- if(atom_len > 8) {
- // copy all the atom (not only payload) for lavc alac decoder
- sh->codecdata_len = atom_len;
- sh->codecdata = malloc(sh->codecdata_len);
- memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len);
- }
- } break;
- case MOV_FOURCC('d','a','m','r'):
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found AMR audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len);
- if (atom_len>14) {
- mp_msg(MSGT_DEMUX, MSGL_V, "mov: vendor: %c%c%c%c Version: %d\n",trak->stdata[36+adjust],trak->stdata[37+adjust],trak->stdata[38+adjust], trak->stdata[39+adjust],trak->stdata[40+adjust]);
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Modes set: %02x%02x\n",trak->stdata[41+adjust],trak->stdata[42+adjust]);
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Mode change period: %d Frames per sample: %d\n",trak->stdata[43+adjust],trak->stdata[44+adjust]);
- }
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unknown audio atom %c%c%c%c (%d)!\n",
- trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust],
- atom_len);
- }
- }
- mp_msg(MSGT_DEMUX, MSGL_V, "Fourcc: %.4s\n",(char *)&trak->fourcc);
-#if 0
- { FILE* f=fopen("stdata.dat","wb");
- fwrite(trak->stdata,trak->stdata_len,1,f);
- fclose(f); }
- { FILE* f=fopen("tkdata.dat","wb");
- fwrite(trak->tkdata,trak->tkdata_len,1,f);
- fclose(f); }
-#endif
- // Emulate WAVEFORMATEX struct:
- sh->wf=calloc(1, sizeof(*sh->wf) + (is_vorbis ? sh->codecdata_len : 0));
- sh->wf->nChannels=sh->channels;
- sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19];
- // sh->wf->nSamplesPerSec=trak->timescale;
- sh->wf->nSamplesPerSec=sh->samplerate;
- if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){
- //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2
- sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec*
- char2int(trak->stdata,32)+char2int(trak->stdata,28)/2)
- /char2int(trak->stdata,28);
- sh->wf->nBlockAlign=char2int(trak->stdata,36);
- } else {
- sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8;
- // workaround for ms11 ima4
- if (sh->format == 0x1100736d && trak->stdata_len >= 36)
- sh->wf->nBlockAlign=char2int(trak->stdata,36);
- }
-
- if(is_vorbis && sh->codecdata_len)
- {
- memcpy(sh->wf+1, sh->codecdata, sh->codecdata_len);
- sh->wf->cbSize = sh->codecdata_len;
- }
- // Selection:
-// if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){
-// // (auto)selected audio track:
-// demuxer->audio->id=priv->track_db;
-// demuxer->audio->sh=sh; sh->ds=demuxer->audio;
-// }
- return 1;
-}
-
-static int gen_sh_video(sh_video_t* sh, mov_track_t* trak, int timescale) {
- int depth, i, entry;
- int flag, start, count_flag, end, palette_count, gray;
- int hdr_ptr = 76; // the byte just after depth
- unsigned char *palette_map;
-
- sh->format=trak->fourcc;
-
- // crude video delay from editlist0 hack ::atm
- if(trak->editlist_size>=1) {
- if(trak->editlist[0].pos == -1) {
- sh->stream_delay = (float)trak->editlist[0].dur/(float)timescale;
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay);
- }
- }
-
-
- if (trak->stdata_len < 78) {
- mp_msg(MSGT_DEMUXER, MSGL_WARN,
- "MOV: Invalid (%d bytes instead of >= 78) video trak desc\n",
- trak->stdata_len);
- return 0;
- }
-
- depth = trak->stdata[75] | (trak->stdata[74] << 8);
- if (trak->fourcc == mmioFOURCC('r', 'a', 'w', ' '))
- sh->format = IMGFMT_RGB | depth;
-
-// stdata[]:
-// 8 short version
-// 10 short revision
-// 12 int vendor_id
-// 16 int temporal_quality
-// 20 int spatial_quality
-// 24 short width
-// 26 short height
-// 28 int h_dpi
-// 32 int v_dpi
-// 36 int 0
-// 40 short frames_per_sample
-// 42 char[4] compressor_name
-// 74 short depth
-// 76 short color_table_id
-// additional atoms may follow,
-// eg esds atom from .MP4 files
-// 78 int atom size
-// 82 char[4] atom type
-// 86 ... atom data
-
- { ImageDescription* id=malloc(8+trak->stdata_len); // safe
- trak->desc=id;
- id->idSize=8+trak->stdata_len;
-// id->cType=bswap_32(trak->fourcc);
- id->cType=le2me_32(trak->fourcc);
- id->version=char2short(trak->stdata,8);
- id->revisionLevel=char2short(trak->stdata,10);
- id->vendor=char2int(trak->stdata,12);
- id->temporalQuality=char2int(trak->stdata,16);
- id->spatialQuality=char2int(trak->stdata,20);
- id->width=char2short(trak->stdata,24);
- id->height=char2short(trak->stdata,26);
- id->hRes=char2int(trak->stdata,28);
- id->vRes=char2int(trak->stdata,32);
- id->dataSize=char2int(trak->stdata,36);
- id->frameCount=char2short(trak->stdata,40);
- memcpy(&id->name,trak->stdata+42,32);
- id->depth=char2short(trak->stdata,74);
- id->clutID=char2short(trak->stdata,76);
- if(trak->stdata_len>78) memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78);
- sh->ImageDesc=id;
-#if 0
- { FILE *f=fopen("ImageDescription","wb");
- fwrite(id,id->idSize,1,f);
- fclose(f);
- }
-#endif
- }
-
- if(trak->stdata_len >= 86) { // extra atoms found
- int pos=78;
- int atom_len;
- while(pos+8<=trak->stdata_len &&
- (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){
- switch(char2int(trak->stdata,pos+4)) { // switch atom type
- case MOV_FOURCC('g','a','m','a'):
- // intfp with gamma value at which movie was captured
- // can be used to gamma correct movie display
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n",
- atom_len);
- break;
- case MOV_FOURCC('f','i','e','l'):
- // 2 char-values (8bit int) that specify field handling
- // see the Apple's QuickTime Fileformat PDF for more info
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported Field-Handling movie atom (%d)!\n",
- atom_len);
- break;
- case MOV_FOURCC('m','j','q','t'):
- // Motion-JPEG default quantization table
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported MJPEG-Quantization movie atom (%d)!\n",
- atom_len);
- break;
- case MOV_FOURCC('m','j','h','t'):
- // Motion-JPEG default huffman table
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported MJPEG-Huffman movie atom (%d)!\n",
- atom_len);
- break;
- case MOV_FOURCC('e','s','d','s'):
- // MPEG4 Elementary Stream Descriptor header
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found MPEG4 movie Elementary Stream Descriptor atom (%d)!\n", atom_len);
- // add code here to save esds header of length atom_len-8
- // beginning at stdata[86] to some variable to pass it
- // on to the decoder ::atmos
- if(atom_len > 8) {
- esds_t esds;
- if(!mp4_parse_esds(trak->stdata+pos+8, atom_len-8, &esds)) {
-
- if(esds.objectTypeId==MP4OTI_MPEG2VisualSimple || esds.objectTypeId==MP4OTI_MPEG2VisualMain ||
- esds.objectTypeId==MP4OTI_MPEG2VisualSNR || esds.objectTypeId==MP4OTI_MPEG2VisualSpatial ||
- esds.objectTypeId==MP4OTI_MPEG2VisualHigh || esds.objectTypeId==MP4OTI_MPEG2Visual422)
- sh->format=mmioFOURCC('m', 'p', 'g', '2');
- else if(esds.objectTypeId==MP4OTI_MPEG1Visual)
- sh->format=mmioFOURCC('m', 'p', 'g', '1');
-
- // dump away the codec specific configuration for the AAC decoder
- trak->stream_header_len = esds.decoderConfigLen;
- trak->stream_header = malloc(trak->stream_header_len);
- memcpy(trak->stream_header, esds.decoderConfig, trak->stream_header_len);
- }
- mp4_free_esds(&esds); // freeup esds mem
- }
- break;
- case MOV_FOURCC('a','v','c','C'):
- // AVC decoder configuration record
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: AVC decoder configuration record atom (%d)!\n", atom_len);
- if(atom_len > 8) {
- int i, poffs, cnt;
- // Parse some parts of avcC, just for fun :)
- // real parsing is done by avc1 decoder
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC version: %d\n", *(trak->stdata+pos+8));
- if (*(trak->stdata+pos+8) != 1)
- mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9));
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC profile: %d\n", *(trak->stdata+pos+9));
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10));
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC level: %d\n", *(trak->stdata+pos+11));
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC nal length size: %d\n", ((*(trak->stdata+pos+12))&0x03)+1);
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f));
- poffs = pos + 14;
- for (i = 0; i < cnt; i++) {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC sps %d have length %d\n", i, AV_RB16(trak->stdata+poffs));
- poffs += AV_RB16(trak->stdata+poffs) + 2;
- }
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs));
- poffs++;
- for (i = 0; i < cnt; i++) {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC pps %d have length %d\n", i, AV_RB16(trak->stdata+poffs));
- poffs += AV_RB16(trak->stdata+poffs) + 2;
- }
- // Copy avcC for the AVC decoder
- // This data will be put in extradata below, where BITMAPINFOHEADER is created
- trak->stream_header_len = atom_len-8;
- trak->stream_header = malloc(trak->stream_header_len);
- memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len);
- }
- break;
- case MOV_FOURCC('d','2','6','3'):
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found H.263 decoder atom %c%c%c%c (%d)!\n", trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],atom_len);
- if (atom_len>10)
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Vendor: %c%c%c%c H.263 level: %d H.263 profile: %d \n", trak->stdata[pos+8],trak->stdata[pos+9],trak->stdata[pos+10],trak->stdata[pos+11],trak->stdata[pos+12],trak->stdata[pos+13]);
- break;
- case 0:
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unknown movie atom %c%c%c%c (%d)!\n",
- trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],
- atom_len);
- }
- if(atom_len<8) break;
- pos+=atom_len;
-// printf("pos=%d max=%d\n",pos,trak->stdata_len);
- }
- }
- sh->fps=trak->timescale/
- ((trak->durmap_size>=1)?(float)trak->durmap[0].dur:1);
- sh->frametime=1.0f/sh->fps;
-
- sh->disp_w=trak->stdata[25]|(trak->stdata[24]<<8);
- sh->disp_h=trak->stdata[27]|(trak->stdata[26]<<8);
- if(trak->tkdata_len>81) {
- // if image size is zero, fallback to display size
- if(!sh->disp_w && !sh->disp_h) {
- sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8);
- sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8);
- } else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){
- // codec and display width differ... use display one for aspect
- sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8);
- sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8);
- }
- }
-
- if(depth>32+8) mp_msg(MSGT_DEMUX, MSGL_INFO,"*** depth = 0x%X\n",depth);
-
- // palettized?
- gray = 0;
- if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale
- if ((depth == 2) || (depth == 4) || (depth == 8))
- palette_count = (1 << depth);
- else
- palette_count = 0;
-
- // emulate BITMAPINFOHEADER:
- if (palette_count)
- {
- sh->bih=calloc(1, sizeof(*sh->bih) + palette_count * 4);
- sh->bih->biSize=40 + palette_count * 4;
- // fetch the relevant fields
- flag = AV_RB16(&trak->stdata[hdr_ptr]);
- hdr_ptr += 2;
- start = AV_RB32(&trak->stdata[hdr_ptr]);
- hdr_ptr += 4;
- count_flag = AV_RB16(&trak->stdata[hdr_ptr]);
- hdr_ptr += 2;
- end = AV_RB16(&trak->stdata[hdr_ptr]);
- hdr_ptr += 2;
- palette_map = (unsigned char *)sh->bih + 40;
- mp_msg(MSGT_DEMUX, MSGL_V, "Allocated %d entries for palette\n",
- palette_count);
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n",
- start, end, count_flag, flag);
-
- /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/
-
- // load default palette
- if (flag & 0x08)
- {
- if (gray)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "Using default QT grayscale palette\n");
- if (palette_count == 16)
- memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4);
- else if (palette_count == 256) {
- memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4);
- if (trak->fourcc == mmioFOURCC('c','v','i','d')) {
- int i;
- // Hack for grayscale CVID, negative palette
- // If you have samples where this is not required contact me (rxt)
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: greyscale cvid with default palette,"
- " enabling negative palette hack.\n");
- for (i = 0; i < 256 * 4; i++)
- palette_map[i] = palette_map[i] ^ 0xff;
- }
- }
- }
- else
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "Using default QT colour palette\n");
- if (palette_count == 4)
- memcpy(palette_map, qt_default_palette_4, 4 * 4);
- else if (palette_count == 16)
- memcpy(palette_map, qt_default_palette_16, 16 * 4);
- else if (palette_count == 256)
- memcpy(palette_map, qt_default_palette_256, 256 * 4);
- }
- }
- // load palette from file
- else
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "Loading palette from file\n");
- for (i = start; i <= end; i++)
- {
- entry = AV_RB16(&trak->stdata[hdr_ptr]);
- hdr_ptr += 2;
- // apparently, if count_flag is set, entry is same as i
- if (count_flag & 0x8000)
- entry = i;
- // only care about top 8 bits of 16-bit R, G, or B value
- if (entry <= palette_count && entry >= 0)
- {
- palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0];
- palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2];
- palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4];
- mp_dbg(MSGT_DEMUX, MSGL_DBG2, "QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n",
- entry, palette_count,
- palette_map[entry * 4 + 2],
- palette_map[entry * 4 + 1],
- palette_map[entry * 4 + 0]);
- }
- else
- mp_msg(MSGT_DEMUX, MSGL_V, "QT palette: skipped entry (out of count): %d of %d\n",
- entry, palette_count);
- hdr_ptr += 6;
- }
- }
- }
- else
- {
- if (trak->fourcc == mmioFOURCC('a','v','c','1')) {
- if (trak->stream_header_len > 0xffffffff - sizeof(*sh->bih)) {
- mp_msg(MSGT_DEMUXER, MSGL_ERR, "Invalid extradata size %d, skipping\n",trak->stream_header_len);
- trak->stream_header_len = 0;
- }
- sh->bih=calloc(1, sizeof(*sh->bih) + trak->stream_header_len);
- sh->bih->biSize=40 + trak->stream_header_len;
- memcpy(((unsigned char *)sh->bih)+40, trak->stream_header, trak->stream_header_len);
- free (trak->stream_header);
- trak->stream_header_len = 0;
- trak->stream_header = NULL;
- } else {
- sh->bih=calloc(1, sizeof(*sh->bih));
- sh->bih->biSize=40;
- }
- }
- sh->bih->biWidth=sh->disp_w;
- sh->bih->biHeight=sh->disp_h;
- sh->bih->biPlanes=0;
- sh->bih->biBitCount=depth;
- sh->bih->biCompression=trak->fourcc;
- sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount);
- if(trak->tkdata_len>81)
- mp_msg(MSGT_DEMUX, MSGL_V, "Display size: %d x %d\n",
- trak->tkdata[77]|(trak->tkdata[76]<<8),
- trak->tkdata[81]|(trak->tkdata[80]<<8));
- mp_msg(MSGT_DEMUX, MSGL_V, "Fourcc: %.4s Codec: '%.*s'\n",(char *)&trak->fourcc,trak->stdata[42]&31,trak->stdata+43);
-
-// if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){
-// // (auto)selected video track:
-// demuxer->video->id=priv->track_db;
-// demuxer->video->sh=sh; sh->ds=demuxer->video;
-// }
- return 1;
-}
-
-static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){
- mov_priv_t* priv=demuxer->priv;
-// printf("lschunks (level=%d,endpos=%x)\n", level, endpos);
- while(1){
- off_t pos;
- off_t len;
- unsigned int id;
- //
- pos=stream_tell(demuxer->stream);
-// printf("stream_tell==%d\n",pos);
- if(pos>=endpos) return; // END
- len=stream_read_dword(demuxer->stream);
-// printf("len==%d\n",len);
- if(len<8) return; // error
- len-=8;
- id=stream_read_dword(demuxer->stream);
- //
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"lschunks %.4s %d\n",(char *)&id,(int)len);
- //
- if(trak){
- if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0)
- return;
- } else { /* not in track */
- switch(id) {
- case MOV_FOURCC('m','v','h','d'): {
- int version = stream_read_char(demuxer->stream);
- stream_skip(demuxer->stream, (version == 1) ? 19 : 11);
- priv->timescale=stream_read_dword(demuxer->stream);
- if (version == 1)
- priv->duration=stream_read_qword(demuxer->stream);
- else
- priv->duration=stream_read_dword(demuxer->stream);
- mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sMovie header (%d bytes): tscale=%d dur=%d\n",level,"",(int)len,
- (int)priv->timescale,(int)priv->duration);
- break;
- }
- case MOV_FOURCC('t','r','a','k'): {
-// if(trak) printf("MOV: Warning! trak in trak?\n");
- if(priv->track_db>=MOV_MAX_TRACKS){
- mp_tmsg(MSGT_DEMUX,MSGL_WARN,"MOV: WARNING: too many tracks");
- return;
- }
- if(!priv->track_db) mp_msg(MSGT_DEMUX, MSGL_V, "--------------\n");
- trak=calloc(1, sizeof(mov_track_t));
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Track #%d:\n",priv->track_db);
- trak->id=priv->track_db;
- priv->tracks[priv->track_db]=trak;
- lschunks(demuxer,level+1,pos+len,trak);
- mov_build_index(trak,priv->timescale);
- switch(trak->type){
- case MOV_TRAK_AUDIO: {
- sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "mov", priv->track_db);
- gen_sh_audio(sh, trak, priv->timescale);
- break;
- }
- case MOV_TRAK_VIDEO: {
- sh_video_t* sh=new_sh_video(demuxer,priv->track_db);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Video stream found, -vid %d\n", "mov", priv->track_db);
- gen_sh_video(sh, trak, priv->timescale);
- break;
- }
- case MOV_TRAK_GENERIC:
- if (trak->fourcc == mmioFOURCC('m','p','4','s') ||
- trak->fourcc == mmioFOURCC('t','x','3','g') ||
- trak->fourcc == mmioFOURCC('t','e','x','t')) {
- sh_sub_t *sh = new_sh_sub(demuxer, priv->track_db);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Subtitle stream found, -sid %d\n", "mov", priv->track_db);
- if (trak->fourcc == mmioFOURCC('m','p','4','s'))
- init_vobsub(sh, trak);
- else {
- sh->type = 'm';
- sub_utf8 = 1;
- }
- } else
- mp_msg(MSGT_DEMUX, MSGL_V, "Generic track - not completely understood! (id: %d)\n",
- trak->id);
- /* XXX: Also this contains the FLASH data */
-
-#if 0
- {
- int pos = stream_tell(demuxer->stream);
- int i;
- int fd;
- char name[20];
-
- for (i=0; i<trak->samples_size; i++)
- {
- char buf[trak->samples[i].size];
- stream_seek(demuxer->stream, trak->samples[i].pos);
- snprintf((char *)&name[0], 20, "samp%d", i);
- fd = open((char *)&name[0], O_CREAT|O_WRONLY);
- stream_read(demuxer->stream, &buf[0], trak->samples[i].size);
- write(fd, &buf[0], trak->samples[i].size);
- close(fd);
- }
- for (i=0; i<trak->chunks_size; i++)
- {
- char buf[trak->length];
- stream_seek(demuxer->stream, trak->chunks[i].pos);
- snprintf((char *)&name[0], 20, "chunk%d", i);
- fd = open((char *)&name[0], O_CREAT|O_WRONLY);
- stream_read(demuxer->stream, &buf[0], trak->length);
- write(fd, &buf[0], trak->length);
- close(fd);
- }
- if (trak->samplesize > 0)
- {
- char *buf;
-
- buf = malloc(trak->samplesize);
- stream_seek(demuxer->stream, trak->chunks[0].pos);
- snprintf((char *)&name[0], 20, "trak%d", trak->id);
- fd = open((char *)&name[0], O_CREAT|O_WRONLY);
- stream_read(demuxer->stream, buf, trak->samplesize);
- write(fd, buf, trak->samplesize);
- close(fd);
- }
- stream_seek(demuxer->stream, pos);
- }
-#endif
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_V, "Unknown track type found (type: %d)\n", trak->type);
- break;
- }
- mp_msg(MSGT_DEMUX, MSGL_V, "--------------\n");
- priv->track_db++;
- trak=NULL;
- break;
- }
-#if !CONFIG_ZLIB
- case MOV_FOURCC('c','m','o','v'): {
- mp_tmsg(MSGT_DEMUX,MSGL_ERR,"MOV: Compressed headers support requires ZLIB!\n");
- return;
- }
-#else
- case MOV_FOURCC('m','o','o','v'):
- case MOV_FOURCC('c','m','o','v'): {
-// mp_tmsg(MSGT_DEMUX,MSGL_ERR,"MOV: Compressed headers support requires ZLIB!\n");
- lschunks(demuxer,level+1,pos+len,NULL);
- break;
- }
- case MOV_FOURCC('d','c','o','m'): {
-// int temp=stream_read_dword(demuxer->stream);
- unsigned int algo=be2me_32(stream_read_dword(demuxer->stream));
- mp_msg(MSGT_DEMUX, MSGL_V, "Compressed header uses %.4s algo!\n",(char *)&algo);
- break;
- }
- case MOV_FOURCC('c','m','v','d'): {
-// int temp=stream_read_dword(demuxer->stream);
- unsigned int moov_sz=stream_read_dword(demuxer->stream);
- unsigned int cmov_sz=len-4;
- unsigned char* cmov_buf;
- unsigned char* moov_buf;
- int zret;
- z_stream zstrm;
- stream_t* backup;
-
- if (moov_sz > UINT_MAX - 16) {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Invalid cmvd atom size %d\n", moov_sz);
- break;
- }
- cmov_buf=malloc(cmov_sz);
- moov_buf=malloc(moov_sz+16);
- mp_msg(MSGT_DEMUX, MSGL_V, "Compressed header size: %d / %d\n",cmov_sz,moov_sz);
-
- stream_read(demuxer->stream,cmov_buf,cmov_sz);
-
- zstrm.zalloc = (alloc_func)0;
- zstrm.zfree = (free_func)0;
- zstrm.opaque = (voidpf)0;
- zstrm.next_in = cmov_buf;
- zstrm.avail_in = cmov_sz;
- zstrm.next_out = moov_buf;
- zstrm.avail_out = moov_sz;
-
- zret = inflateInit(&zstrm);
- if (zret != Z_OK)
- { mp_msg(MSGT_DEMUX, MSGL_ERR, "QT cmov: inflateInit err %d\n",zret);
- return;
- }
- zret = inflate(&zstrm, Z_NO_FLUSH);
- if ((zret != Z_OK) && (zret != Z_STREAM_END))
- { mp_msg(MSGT_DEMUX, MSGL_ERR, "QT cmov inflate: ERR %d\n",zret);
- return;
- }
-#if 0
- else {
- FILE *DecOut;
- DecOut = fopen("Out.bin", "w");
- fwrite(moov_buf, 1, moov_sz, DecOut);
- fclose(DecOut);
- }
-#endif
- if(moov_sz != zstrm.total_out)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Warning! moov size differs cmov: %d zlib: %ld\n",moov_sz,zstrm.total_out);
- zret = inflateEnd(&zstrm);
-
- backup=demuxer->stream;
- demuxer->stream=new_memory_stream(moov_buf,moov_sz);
- stream_skip(demuxer->stream,8);
- lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov'
- //free_stream(demuxer->stream);
- demuxer->stream=backup;
- free(cmov_buf);
- free(moov_buf);
- break;
- }
-#endif
- case MOV_FOURCC('u','d','t','a'):
- {
- unsigned int udta_id;
- off_t udta_len;
- off_t udta_size = len;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "mov: user data record found\n");
- mp_msg(MSGT_DEMUX, MSGL_V, "Quicktime Clip Info:\n");
-
- while((len > 8) && (udta_size > 8))
- {
- udta_len = stream_read_dword(demuxer->stream);
- udta_id = stream_read_dword(demuxer->stream);
- udta_size -= 8;
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "udta_id: %.4s (len: %"PRId64")\n", (char *)&udta_id, (int64_t)udta_len);
- switch (udta_id)
- {
- case MOV_FOURCC(0xa9,'c','p','y'):
- case MOV_FOURCC(0xa9,'d','a','y'):
- case MOV_FOURCC(0xa9,'d','i','r'):
- /* 0xa9,'e','d','1' - '9' : edit timestamps */
- case MOV_FOURCC(0xa9,'f','m','t'):
- case MOV_FOURCC(0xa9,'i','n','f'):
- case MOV_FOURCC(0xa9,'p','r','d'):
- case MOV_FOURCC(0xa9,'p','r','f'):
- case MOV_FOURCC(0xa9,'r','e','q'):
- case MOV_FOURCC(0xa9,'s','r','c'):
- case MOV_FOURCC('n','a','m','e'):
- case MOV_FOURCC(0xa9,'n','a','m'):
- case MOV_FOURCC(0xa9,'A','R','T'):
- case MOV_FOURCC(0xa9,'c','m','t'):
- case MOV_FOURCC(0xa9,'a','u','t'):
- case MOV_FOURCC(0xa9,'s','w','r'):
- {
- off_t text_len = stream_read_word(demuxer->stream);
- char text[text_len+2+1];
- stream_read(demuxer->stream, (char *)&text, text_len+2);
- text[text_len+2] = 0x0;
- switch(udta_id)
- {
- case MOV_FOURCC(0xa9,'a','u','t'):
- demux_info_add(demuxer, "author", &text[2]);
- mp_msg(MSGT_DEMUX, MSGL_V, " Author: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'c','p','y'):
- demux_info_add(demuxer, "copyright", &text[2]);
- mp_msg(MSGT_DEMUX, MSGL_V, " Copyright: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'i','n','f'):
- mp_msg(MSGT_DEMUX, MSGL_V, " Info: %s\n", &text[2]);
- break;
- case MOV_FOURCC('n','a','m','e'):
- case MOV_FOURCC(0xa9,'n','a','m'):
- demux_info_add(demuxer, "title", &text[2]);
- mp_msg(MSGT_DEMUX, MSGL_V, " Name: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'A','R','T'):
- mp_msg(MSGT_DEMUX, MSGL_V, " Artist: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'d','i','r'):
- mp_msg(MSGT_DEMUX, MSGL_V, " Director: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'c','m','t'):
- demux_info_add(demuxer, "comments", &text[2]);
- mp_msg(MSGT_DEMUX, MSGL_V, " Comment: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'r','e','q'):
- mp_msg(MSGT_DEMUX, MSGL_V, " Requirements: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'s','w','r'):
- demux_info_add(demuxer, "encoder", &text[2]);
- mp_msg(MSGT_DEMUX, MSGL_V, " Software: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'d','a','y'):
- mp_msg(MSGT_DEMUX, MSGL_V, " Creation timestamp: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'f','m','t'):
- mp_msg(MSGT_DEMUX, MSGL_V, " Format: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'p','r','d'):
- mp_msg(MSGT_DEMUX, MSGL_V, " Producer: %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'p','r','f'):
- mp_msg(MSGT_DEMUX, MSGL_V, " Performer(s): %s\n", &text[2]);
- break;
- case MOV_FOURCC(0xa9,'s','r','c'):
- mp_msg(MSGT_DEMUX, MSGL_V, " Source providers: %s\n", &text[2]);
- break;
- }
- udta_size -= 4+text_len;
- break;
- }
- /* some other shits: WLOC - window location,
- LOOP - looping style,
- SelO - play only selected frames
- AllF - play all frames
- */
- case MOV_FOURCC('W','L','O','C'):
- case MOV_FOURCC('L','O','O','P'):
- case MOV_FOURCC('S','e','l','O'):
- case MOV_FOURCC('A','l','l','F'):
- default:
- {
- if( udta_len>udta_size)
- udta_len=udta_size;
- {
- stream_skip(demuxer->stream, udta_len-4-4);
- udta_size -= udta_len;
- }
- }
- }
- }
- break;
- } /* eof udta */
- default:
- id = be2me_32(id);
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len);
- } /* endof switch */
- } /* endof else */
-
- pos+=len+8;
- if(pos>=endpos) break;
- if(!stream_seek(demuxer->stream,pos)) break;
- }
-}
-
-static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id,
- off_t pos, off_t len, mov_track_t* trak)
-{
- switch(id) {
- case MOV_FOURCC('m','d','a','t'): {
- mp_msg(MSGT_DEMUX,MSGL_WARN,"Hmm, strange MOV, parsing mdat in lschunks?\n");
- return -1;
- }
- case MOV_FOURCC('f','r','e','e'):
- case MOV_FOURCC('u','d','t','a'):
- /* here not supported :p */
- break;
- case MOV_FOURCC('t','k','h','d'): {
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sTrack header!\n", level, "");
- // read codec data
- trak->tkdata_len = len;
- trak->tkdata = malloc(trak->tkdata_len);
- stream_read(demuxer->stream, trak->tkdata, trak->tkdata_len);
-/*
-0 1 Version
-1 3 Flags
-4 4 Creation time
-8 4 Modification time
-12 4 Track ID
-16 4 Reserved
-20 4 Duration
-24 8 Reserved
-32 2 Layer
-34 2 Alternate group
-36 2 Volume
-38 2 Reserved
-40 36 Matrix structure
-76 4 Track width
-80 4 Track height
-*/
- mp_msg(MSGT_DEMUX, MSGL_V,
- "tkhd len=%d ver=%d flags=0x%X id=%d dur=%d lay=%d vol=%d\n",
- trak->tkdata_len, trak->tkdata[0], trak->tkdata[1],
- char2int(trak->tkdata, 12), // id
- char2int(trak->tkdata, 20), // duration
- char2short(trak->tkdata, 32), // layer
- char2short(trak->tkdata, 36)); // volume
- break;
- }
- case MOV_FOURCC('m','d','h','d'): {
- int version = stream_read_char(demuxer->stream);
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sMedia header!\n", level, "");
- stream_skip(demuxer->stream, (version == 1) ? 19 : 11);
- // read timescale
- trak->timescale = stream_read_dword(demuxer->stream);
- // read length
- if (version == 1)
- trak->length = stream_read_qword(demuxer->stream);
- else
- trak->length = stream_read_dword(demuxer->stream);
- break;
- }
- case MOV_FOURCC('h','d','l','r'): {
- av_unused unsigned int tmp = stream_read_dword(demuxer->stream);
- unsigned int type = stream_read_dword_le(demuxer->stream);
- unsigned int subtype = stream_read_dword_le(demuxer->stream);
- unsigned int manufact = stream_read_dword_le(demuxer->stream);
- av_unused unsigned int comp_flags = stream_read_dword(demuxer->stream);
- av_unused unsigned int comp_mask = stream_read_dword(demuxer->stream);
- int len = stream_read_char(demuxer->stream);
- char* str = malloc(len + 1);
- stream_read(demuxer->stream, str, len);
- str[len] = 0;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*sHandler header: %.4s/%.4s (%.4s) %s\n", level, "",
- (char *)&type, (char *)&subtype, (char *)&manufact, str);
- free(str);
- switch(bswap_32(type)) {
- case MOV_FOURCC('m','h','l','r'):
- trak->media_handler = bswap_32(subtype);
- break;
- case MOV_FOURCC('d','h','l','r'):
- trak->data_handler = bswap_32(subtype);
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: unknown handler class: 0x%X (%.4s)\n",
- bswap_32(type), (char *)&type);
- }
- break;
- }
- case MOV_FOURCC('v','m','h','d'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sVideo header!\n", level, "");
- trak->type = MOV_TRAK_VIDEO;
- // read video data
- break;
- }
- case MOV_FOURCC('s','m','h','d'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sSound header!\n", level, "");
- trak->type = MOV_TRAK_AUDIO;
- // read audio data
- break;
- }
- case MOV_FOURCC('g','m','h','d'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sGeneric header!\n", level, "");
- trak->type = MOV_TRAK_GENERIC;
- break;
- }
- case MOV_FOURCC('n','m','h','d'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sGeneric header!\n", level, "");
- trak->type = MOV_TRAK_GENERIC;
- break;
- }
- case MOV_FOURCC('s','t','s','d'): {
- int i = stream_read_dword(demuxer->stream); // temp!
- int count = stream_read_dword(demuxer->stream);
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sDescription list! (cnt:%d)\n",
- level, "", count);
- for (i = 0; i < count; i++) {
- off_t pos = stream_tell(demuxer->stream);
- off_t len = stream_read_dword(demuxer->stream);
- unsigned int fourcc = stream_read_dword_le(demuxer->stream);
- /* some files created with Broadcast 2000 (e.g. ilacetest.mov)
- contain raw I420 video but have a yv12 fourcc */
- if (fourcc == mmioFOURCC('y','v','1','2'))
- fourcc = mmioFOURCC('I','4','2','0');
- if (len < 8)
- break; // error
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*s desc #%d: %.4s (%"PRId64" bytes)\n", level, "",
- i, (char *)&fourcc, (int64_t)len - 16);
- if (fourcc != trak->fourcc && i)
- mp_tmsg(MSGT_DEMUX, MSGL_WARN, "MOV: WARNING: Variable FourCC detected!?\n");
-// if(!i)
- {
- trak->fourcc = fourcc;
- // read type specific (audio/video/time/text etc) header
- // NOTE: trak type is not yet known at this point :(((
- trak->stdata_len = len - 8;
- trak->stdata = malloc(trak->stdata_len);
- stream_read(demuxer->stream, trak->stdata, trak->stdata_len);
- }
- if (!stream_seek(demuxer->stream, pos + len))
- break;
- }
- break;
- }
- case MOV_FOURCC('s','t','t','s'): {
- av_unused int temp = stream_read_dword(demuxer->stream);
- int len = stream_read_dword(demuxer->stream);
- int i;
- unsigned int pts = 0;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*sSample duration table! (%d blocks)\n", level, "",
- len);
- free(trak->durmap);
- trak->durmap = calloc(len, sizeof(mov_durmap_t));
- trak->durmap_size = trak->durmap ? len : 0;
- for (i = 0; i < trak->durmap_size; i++) {
- trak->durmap[i].num = stream_read_dword(demuxer->stream);
- trak->durmap[i].dur = stream_read_dword(demuxer->stream);
- pts += trak->durmap[i].num * trak->durmap[i].dur;
- }
- if (trak->length != pts)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Warning! pts=%d length=%d\n",
- pts, trak->length);
- break;
- }
- case MOV_FOURCC('s','t','s','c'): {
- int temp = stream_read_dword(demuxer->stream);
- int len = stream_read_dword(demuxer->stream);
- int ver = (temp << 24);
- int flags = (temp << 16) | (temp << 8) | temp;
- int i;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*sSample->Chunk mapping table! (%d blocks) (ver:%d,flags:%d)\n", level, "",
- len, ver, flags);
- // read data:
- free(trak->chunkmap);
- trak->chunkmap = calloc(len, sizeof(mov_chunkmap_t));
- trak->chunkmap_size = trak->chunkmap ? len : 0;
- for (i = 0; i < trak->chunkmap_size; i++) {
- trak->chunkmap[i].first = stream_read_dword(demuxer->stream) - 1;
- trak->chunkmap[i].spc = stream_read_dword(demuxer->stream);
- trak->chunkmap[i].sdid = stream_read_dword(demuxer->stream);
- }
- break;
- }
- case MOV_FOURCC('s','t','s','z'): {
- int temp = stream_read_dword(demuxer->stream);
- int ss=stream_read_dword(demuxer->stream);
- int ver = (temp << 24);
- int flags = (temp << 16) | (temp << 8) | temp;
- int entries = stream_read_dword(demuxer->stream);
- int i;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*sSample size table! (entries=%d ss=%d) (ver:%d,flags:%d)\n", level, "",
- entries, ss, ver, flags);
- trak->samplesize = ss;
- if (!ss) {
- // variable samplesize
- free(trak->samples);
- trak->samples = calloc(entries, sizeof(mov_sample_t));
- trak->samples_size = trak->samples ? entries : 0;
- for (i = 0; i < trak->samples_size; i++)
- trak->samples[i].size = stream_read_dword(demuxer->stream);
- }
- break;
- }
- case MOV_FOURCC('s','t','c','o'): {
- av_unused int temp = stream_read_dword(demuxer->stream);
- int len = stream_read_dword(demuxer->stream);
- int i;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*sChunk offset table! (%d chunks)\n", level, "",
- len);
- // extend array if needed:
- if (len > trak->chunks_size) {
- free(trak->chunks);
- trak->chunks = calloc(len, sizeof(mov_chunk_t));
- trak->chunks_size = trak->chunks ? len : 0;
- }
- // read elements:
- for(i = 0; i < trak->chunks_size; i++)
- trak->chunks[i].pos = stream_read_dword(demuxer->stream);
- break;
- }
- case MOV_FOURCC('c','o','6','4'): {
- av_unused int temp = stream_read_dword(demuxer->stream);
- int len = stream_read_dword(demuxer->stream);
- int i;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*s64bit chunk offset table! (%d chunks)\n", level, "",
- len);
- // extend array if needed:
- if (len > trak->chunks_size) {
- free(trak->chunks);
- trak->chunks = calloc(len, sizeof(mov_chunk_t));
- trak->chunks_size = trak->chunks ? len : 0;
- }
- // read elements:
- for (i = 0; i < trak->chunks_size; i++) {
-#ifndef _LARGEFILE_SOURCE
- if (stream_read_dword(demuxer->stream) != 0)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Chunk %d has got 64bit address, but you've MPlayer compiled without LARGEFILE support!\n", i);
- trak->chunks[i].pos = stream_read_dword(demuxer->stream);
-#else
- trak->chunks[i].pos = stream_read_qword(demuxer->stream);
-#endif
- }
- break;
- }
- case MOV_FOURCC('s','t','s','s'): {
- int temp = stream_read_dword(demuxer->stream);
- int entries = stream_read_dword(demuxer->stream);
- int ver = (temp << 24);
- int flags = (temp << 16) | (temp<<8) | temp;
- int i;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*sSyncing samples (keyframes) table! (%d entries) (ver:%d,flags:%d)\n", level, "",
- entries, ver, flags);
- free(trak->keyframes);
- trak->keyframes = calloc(entries, sizeof(unsigned int));
- trak->keyframes_size = trak->keyframes ? entries : 0;
- for (i = 0; i < trak->keyframes_size; i++)
- trak->keyframes[i] = stream_read_dword(demuxer->stream) - 1;
- break;
- }
- case MOV_FOURCC('m','d','i','a'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sMedia stream!\n", level, "");
- lschunks(demuxer, level + 1, pos + len, trak);
- break;
- }
- case MOV_FOURCC('m','i','n','f'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sMedia info!\n", level, "");
- lschunks(demuxer, level + 1 ,pos + len, trak);
- break;
- }
- case MOV_FOURCC('s','t','b','l'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sSample info!\n", level, "");
- lschunks(demuxer, level + 1, pos + len, trak);
- break;
- }
- case MOV_FOURCC('e','d','t','s'): {
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sEdit atom!\n", level, "");
- lschunks(demuxer, level + 1, pos + len, trak);
- break;
- }
- case MOV_FOURCC('e','l','s','t'): {
- int temp = stream_read_dword(demuxer->stream);
- int entries = stream_read_dword(demuxer->stream);
- int ver = (temp << 24);
- int flags = (temp << 16) | (temp << 8) | temp;
- int i;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*sEdit list table (%d entries) (ver:%d,flags:%d)\n", level, "",
- entries, ver, flags);
-#if 1
- free(trak->editlist);
- trak->editlist = calloc(entries, sizeof(mov_editlist_t));
- trak->editlist_size = trak->editlist ? entries : 0;
- for (i = 0; i < trak->editlist_size; i++) {
- int dur = stream_read_dword(demuxer->stream);
- int mt = stream_read_dword(demuxer->stream);
- int mr = stream_read_dword(demuxer->stream); // 16.16fp
- trak->editlist[i].dur = dur;
- trak->editlist[i].pos = mt;
- trak->editlist[i].speed = mr;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "MOV: %*s entry#%d: duration: %d start time: %d speed: %3.1fx\n", level, "",
- i, dur, mt, (float)mr/65536.0f);
- }
-#endif
- break;
- }
- case MOV_FOURCC('c','o','d','e'): {
- /* XXX: Implement atom 'code' for FLASH support */
- break;
- }
- default:
- id = be2me_32(id);
- mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len);
- break;
- }//switch(id)
- return 0;
-}
-
-static demuxer_t* mov_read_header(demuxer_t* demuxer){
- struct MPOpts *opts = demuxer->opts;
- mov_priv_t* priv=demuxer->priv;
- int t_no;
- int best_a_id=-1, best_a_len=0;
- int best_v_id=-1, best_v_len=0;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG3, "mov_read_header!\n");
-
- // Parse header:
- stream_reset(demuxer->stream);
- if(!stream_seek(demuxer->stream,priv->moov_start))
- {
- mp_msg(MSGT_DEMUX,MSGL_ERR,"MOV: Cannot seek to the beginning of the Movie header (0x%"PRIx64")\n",
- (int64_t)priv->moov_start);
- return 0;
- }
- lschunks(demuxer, 0, priv->moov_end, NULL);
- // just in case we have hit eof while parsing...
- demuxer->stream->eof = 0;
-// mp_msg(MSGT_DEMUX, MSGL_INFO, "--------------\n");
-
- // find the best (longest) streams:
- for(t_no=0;t_no<priv->track_db;t_no++){
- mov_track_t* trak=priv->tracks[t_no];
- int len=(trak->samplesize) ? trak->chunks_size : trak->samples_size;
- if(demuxer->a_streams[t_no]){ // need audio
- if(len>best_a_len){ best_a_len=len; best_a_id=t_no; }
- }
- if(demuxer->v_streams[t_no]){ // need video
- if(len>best_v_len){ best_v_len=len; best_v_id=t_no; }
- }
- }
- mp_msg(MSGT_DEMUX, MSGL_V, "MOV: longest streams: A: #%d (%d samples) V: #%d (%d samples)\n",
- best_a_id,best_a_len,best_v_id,best_v_len);
- if(demuxer->audio->id==-1 && best_a_id>=0) demuxer->audio->id=best_a_id;
- if(demuxer->video->id==-1 && best_v_id>=0) demuxer->video->id=best_v_id;
-
- // setup sh pointers:
- if(demuxer->audio->id>=0){
- sh_audio_t* sh=demuxer->a_streams[demuxer->audio->id];
- if(sh){
- demuxer->audio->sh=sh; sh->ds=demuxer->audio;
- } else {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected audio stream (%d) does not exist\n",demuxer->audio->id);
- demuxer->audio->id=-2;
- }
- }
- if(demuxer->video->id>=0){
- sh_video_t* sh=demuxer->v_streams[demuxer->video->id];
- if(sh){
- demuxer->video->sh=sh; sh->ds=demuxer->video;
- } else {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected video stream (%d) does not exist\n",demuxer->video->id);
- demuxer->video->id=-2;
- }
- }
- if(demuxer->sub->id>=0){
- sh_sub_t* sh=demuxer->s_streams[demuxer->sub->id];
- if(sh){
- demuxer->sub->sh=sh;
- } else {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected subtitle stream (%d) does not exist\n",demuxer->sub->id);
- demuxer->sub->id=-2;
- }
- }
-
- if(demuxer->video->id<0 && demuxer->audio->id<0) {
- /* No AV streams found. Try to find an MPEG stream. */
- for(t_no=0;t_no<priv->track_db;t_no++){
- mov_track_t* trak=priv->tracks[t_no];
- if(trak->media_handler == MOV_FOURCC('M','P','E','G')) {
- stream_t *s;
- demuxer_t *od;
-
- demuxer->video->id = t_no;
- s = new_ds_stream(demuxer->video);
- od = demux_open(opts, s, DEMUXER_TYPE_MPEG_PS, -1, -1, -1, NULL);
- if(od) return new_demuxers_demuxer(od, od, od);
- demuxer->video->id = -2; //new linked demuxer couldn't be allocated
- break;
- }
- }
- }
-
-#if 0
- if( mp_msg_test(MSGT_DEMUX,MSGL_DBG3) ){
- for(t_no=0;t_no<priv->track_db;t_no++){
- mov_track_t* trak=priv->tracks[t_no];
- if(trak->type==MOV_TRAK_GENERIC){
- int i;
- int fd;
- char name[20];
- mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Track #%d: Extracting %d data chunks to files\n",t_no,trak->samples_size);
- for (i=0; i<trak->samples_size; i++)
- {
- int len=trak->samples[i].size;
- char buf[len];
- stream_seek(demuxer->stream, trak->samples[i].pos);
- snprintf(name, 20, "t%02d-s%03d.%s", t_no,i,
- (trak->media_handler==MOV_FOURCC('f','l','s','h')) ?
- "swf":"dump");
- fd = open(name, O_CREAT|O_WRONLY);
-// { int j;
-// for(j=0;j<trak->stdata_len-3; j++)
-// printf("stdata[%d]=0x%X ize=0x%X\n",j,char2int(trak->stdata,j),MOV_FOURCC('z','l','i','b'));
-// }
- if( //trak->media_handler==MOV_FOURCC('s','p','r','t') &&
- trak->stdata_len>=16 &&
- char2int(trak->stdata,12)==MOV_FOURCC('z','l','i','b')
- ){
- int newlen=stream_read_dword(demuxer->stream);
-#if CONFIG_ZLIB
- // unzip:
- z_stream zstrm;
- int zret;
- char buf2[newlen];
-
- len-=4;
- stream_read(demuxer->stream, buf, len);
-
- zstrm.zalloc = (alloc_func)0;
- zstrm.zfree = (free_func)0;
- zstrm.opaque = (voidpf)0;
- zstrm.next_in = buf;
- zstrm.avail_in = len;
- zstrm.next_out = buf2;
- zstrm.avail_out = newlen;
-
- zret = inflateInit(&zstrm);
- zret = inflate(&zstrm, Z_NO_FLUSH);
- if(newlen != zstrm.total_out)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Warning! unzipped frame size differs hdr: %d zlib: %ld\n",newlen,zstrm.total_out);
-
- write(fd, buf2, newlen);
- } else {
-#else
- len-=4;
- mp_msg(MSGT_DEMUX, MSGL_INFO, "******* ZLIB COMPRESSED SAMPLE!!!!! (%d->%d bytes) *******\n",len,newlen);
- }
- {
-#endif
- stream_read(demuxer->stream, buf, len);
- write(fd, buf, len);
- }
- close(fd);
- }
- }
- }
- }
- demuxer->stream->eof = 0;
-#endif
-
- return demuxer;
-}
-
-/**
- * \brief return the mov track that belongs to a demuxer stream
- * \param ds the demuxer stream, may be NULL
- * \return the mov track info structure belonging to the stream,
- * NULL if not found
- */
-static mov_track_t *stream_track(mov_priv_t *priv, demux_stream_t *ds) {
- if (ds && (ds->id >= 0) && (ds->id < priv->track_db))
- return priv->tracks[ds->id];
- return NULL;
-}
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_mov_fill_buffer(demuxer_t *demuxer,demux_stream_t* ds){
- mov_priv_t* priv=demuxer->priv;
- mov_track_t* trak=NULL;
- float pts;
- int x;
- off_t pos;
-
- if (ds->eof) return 0;
- trak = stream_track(priv, ds);
- if (!trak) return 0;
-
-if(trak->samplesize){
- // read chunk:
- if(trak->pos>=trak->chunks_size) return 0; // EOF
- stream_seek(demuxer->stream,trak->chunks[trak->pos].pos);
- pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale;
- if(trak->samplesize!=1)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "WARNING! Samplesize(%d) != 1\n",
- trak->samplesize);
- if((trak->fourcc != MOV_FOURCC('t','w','o','s')) && (trak->fourcc != MOV_FOURCC('s','o','w','t')))
- x=trak->chunks[trak->pos].size*trak->samplesize;
- else
- x=trak->chunks[trak->pos].size;
- }
- else
- x=trak->chunks[trak->pos].size;
-// printf("X = %d\n", x);
- /* the following stuff is audio related */
- if (trak->type == MOV_TRAK_AUDIO){
- if(trak->stdata_len>=44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){
- // stsd version 1 - we have audio compression ratio info:
- x/=char2int(trak->stdata,28); // samples/packet
-// x*=char2int(trak->stdata,32); // bytes/packet
- x*=char2int(trak->stdata,36); // bytes/frame
- } else {
- if(ds->ss_div && ds->ss_mul){
- // workaround for buggy files like 7up-high-traffic-areas.mov,
- // with missing stsd v1 header containing compression rate
- x/=ds->ss_div; x*=ds->ss_mul; // compression ratio fix ! HACK !
- } else {
- x*=trak->nchannels;
- x*=trak->samplebytes;
- }
- }
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Audio sample %d bytes pts %5.3f\n",trak->chunks[trak->pos].size*trak->samplesize,pts);
- } /* MOV_TRAK_AUDIO */
- pos=trak->chunks[trak->pos].pos;
-} else {
- int frame=trak->pos;
- // editlist support:
- if(trak->type == MOV_TRAK_VIDEO && trak->editlist_size>=1){
- // find the right editlist entry:
- if(frame<trak->editlist[trak->editlist_pos].start_frame)
- trak->editlist_pos=0;
- while(trak->editlist_pos<trak->editlist_size-1 &&
- frame>=trak->editlist[trak->editlist_pos+1].start_frame)
- ++trak->editlist_pos;
- if(frame>=trak->editlist[trak->editlist_pos].start_frame+
- trak->editlist[trak->editlist_pos].frames) return 0; // EOF
- // calc real frame index:
- frame-=trak->editlist[trak->editlist_pos].start_frame;
- frame+=trak->editlist[trak->editlist_pos].start_sample;
- // calc pts:
- pts=(float)(trak->samples[frame].pts+
- trak->editlist[trak->editlist_pos].pts_offset)/(float)trak->timescale;
- } else {
- if(frame>=trak->samples_size) return 0; // EOF
- pts=(float)trak->samples[frame].pts/(float)trak->timescale;
- }
- // read sample:
- stream_seek(demuxer->stream,trak->samples[frame].pos);
- x=trak->samples[frame].size;
- pos=trak->samples[frame].pos;
-}
-if(trak->pos==0 && trak->stream_header_len>0){
- // we have to append the stream header...
- demux_packet_t* dp=new_demux_packet(x+trak->stream_header_len);
- memcpy(dp->buffer,trak->stream_header,trak->stream_header_len);
- stream_read(demuxer->stream,dp->buffer+trak->stream_header_len,x);
- free(trak->stream_header);
- trak->stream_header = NULL;
- trak->stream_header_len = 0;
- dp->pts=pts;
- dp->pos=pos; // FIXME?
- ds_add_packet(ds,dp);
-} else
- ds_read_packet(ds,demuxer->stream,x,pts,pos,0);
-
- ++trak->pos;
-
- trak = NULL;
- if (demuxer->sub->id >= 0 && demuxer->sub->id < priv->track_db)
- trak = priv->tracks[demuxer->sub->id];
- if (trak) {
- int samplenr = 0;
- while (samplenr < trak->samples_size) {
- double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale;
- if (subpts >= pts) break;
- samplenr++;
- }
- samplenr--;
- if (samplenr < 0)
- vo_sub = NULL;
- else if (samplenr != priv->current_sub) {
- off_t pos = trak->samples[samplenr].pos;
- int len = trak->samples[samplenr].size;
- double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale;
- stream_seek(demuxer->stream, pos);
- ds_read_packet(demuxer->sub, demuxer->stream, len, subpts, pos, 0);
- priv->current_sub = samplenr;
- }
- }
-
- return 1;
-
-}
-
-static float mov_seek_track(mov_track_t* trak,float pts,int flags){
-
-// printf("MOV track seek called %5.3f \n",pts);
- if(flags&SEEK_FACTOR) pts*=trak->length; else pts*=(float)trak->timescale;
-
-if(trak->samplesize){
- int sample=pts/trak->duration;
-// printf("MOV track seek - chunk: %d (pts: %5.3f dur=%d) \n",sample,pts,trak->duration);
- if(!(flags&SEEK_ABSOLUTE)) sample+=trak->chunks[trak->pos].sample; // relative
- trak->pos=0;
- while(trak->pos<trak->chunks_size && trak->chunks[trak->pos].sample<sample) ++trak->pos;
- if (trak->pos == trak->chunks_size) return -1;
- pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale;
-} else {
- unsigned int ipts;
- if(!(flags&SEEK_ABSOLUTE)) pts+=trak->samples[trak->pos].pts;
- if(pts<0) pts=0;
- ipts=pts;
- //printf("MOV track seek - sample: %d \n",ipts);
- for(trak->pos=0;trak->pos<trak->samples_size;++trak->pos){
- if(trak->samples[trak->pos].pts>=ipts) break; // found it!
- }
- if (trak->pos == trak->samples_size) return -1;
- if(trak->keyframes_size){
- // find nearest keyframe
- int i;
- for(i=0;i<trak->keyframes_size;i++){
- if(trak->keyframes[i]>=trak->pos) break;
- }
- if (i == trak->keyframes_size) return -1;
- if(i>0 && (trak->keyframes[i]-trak->pos) > (trak->pos-trak->keyframes[i-1]))
- --i;
- trak->pos=trak->keyframes[i];
-// printf("nearest keyframe: %d \n",trak->pos);
- }
- pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale;
-}
-
-// printf("MOV track seek done: %5.3f \n",pts);
-
-return pts;
-}
-
-static void demux_seek_mov(demuxer_t *demuxer,float pts,float audio_delay,int flags){
- mov_priv_t* priv=demuxer->priv;
- demux_stream_t* ds;
- mov_track_t* trak;
-
-// printf("MOV seek called %5.3f flag=%d \n",pts,flags);
-
- ds=demuxer->video;
- trak = stream_track(priv, ds);
- if (trak) {
- //if(flags&2) pts*=(float)trak->length/(float)trak->timescale;
- //if(!(flags&1)) pts+=ds->pts;
- ds->pts=mov_seek_track(trak,pts,flags);
- if (ds->pts < 0) ds->eof = 1;
- else pts = ds->pts;
- flags=1; // absolute seconds
- }
-
- ds=demuxer->audio;
- trak = stream_track(priv, ds);
- if (trak) {
- //if(flags&2) pts*=(float)trak->length/(float)trak->timescale;
- //if(!(flags&1)) pts+=ds->pts;
- ds->pts=mov_seek_track(trak,pts,flags);
- if (ds->pts < 0) ds->eof = 1;
- }
-
-}
-
-static int demux_mov_control(demuxer_t *demuxer, int cmd, void *arg){
- mov_track_t* track;
-
- // try the video track
- track = stream_track(demuxer->priv, demuxer->video);
- if (!track || !track->length)
- // otherwise try to get the info from the audio track
- track = stream_track(demuxer->priv, demuxer->audio);
-
- if (!track || !track->length)
- return DEMUXER_CTRL_DONTKNOW;
-
- switch(cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- if (!track->timescale)
- return DEMUXER_CTRL_DONTKNOW;
- *((double *)arg) = (double)track->length / track->timescale;
- return DEMUXER_CTRL_OK;
-
- case DEMUXER_CTRL_GET_PERCENT_POS:
- {
- off_t pos = track->pos;
- if (track->durmap_size >= 1)
- pos *= track->durmap[0].dur;
- *((int *)arg) = (int)(100 * pos / track->length);
- return DEMUXER_CTRL_OK;
- }
- }
- return DEMUXER_CTRL_NOTIMPL;
-}
-
-
-const demuxer_desc_t demuxer_desc_mov = {
- "Quicktime/MP4 demuxer",
- "mov",
- "Quicktime/MOV",
- "Arpi, Al3x, Atmos, others",
- "Handles Quicktime, MP4, 3GP",
- DEMUXER_TYPE_MOV,
- 0, // slow autodetect
- mov_check_file,
- demux_mov_fill_buffer,
- mov_read_header,
- demux_close_mov,
- demux_seek_mov,
- demux_mov_control
-};
diff --git a/libmpdemux/demux_mov.h b/libmpdemux/demux_mov.h
deleted file mode 100644
index 8aa515c349..0000000000
--- a/libmpdemux/demux_mov.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_DEMUX_MOV_H
-#define MPLAYER_DEMUX_MOV_H
-
-unsigned int store_ughvlc(unsigned char *s, unsigned int v);
-
-#endif /* MPLAYER_DEMUX_MOV_H */
diff --git a/libmpdemux/demux_mpc.c b/libmpdemux/demux_mpc.c
deleted file mode 100644
index 234eed45da..0000000000
--- a/libmpdemux/demux_mpc.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * demuxer for Musepack v7 bitstream
- * copyright (c) 2005 Reimar Doeffinger <Reimar.Doeffinger@stud.uni-karlsruhe.de>
- *
- * This code may be be relicensed under the terms of the GNU LGPL when it
- * becomes part of the FFmpeg project (ffmpeg.org)
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "mp_msg.h"
-#include "libavutil/common.h"
-#include "mpbswap.h"
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-
-#define HDR_SIZE (6 * 4)
-
-typedef struct da_priv {
- float last_pts;
- float pts_per_packet;
- uint32_t dword;
- int pos;
- float length;
-} da_priv_t;
-
-static uint32_t get_bits(da_priv_t* priv, stream_t* s, int bits) {
- uint32_t out = priv->dword;
- uint32_t mask = (1 << bits) - 1;
- priv->pos += bits;
- if (priv->pos < 32) {
- out >>= (32 - priv->pos);
- }
- else {
- stream_read(s, (void *)&priv->dword, 4);
- priv->dword = le2me_32(priv->dword);
- priv->pos -= 32;
- if (priv->pos) {
- out <<= priv->pos;
- out |= priv->dword >> (32 - priv->pos);
- }
- }
- return out & mask;
-}
-
-static int demux_mpc_check(demuxer_t* demuxer) {
- stream_t *s = demuxer->stream;
- uint8_t hdr[HDR_SIZE];
- int i;
-
- if (stream_read(s, hdr, HDR_SIZE) != HDR_SIZE)
- return 0;
- for (i = 0; i < 30000 && !s->eof; i++) {
- if (hdr[0] == 'M' && hdr[1] == 'P' && hdr[2] == '+')
- break;
- memmove(hdr, &hdr[1], HDR_SIZE - 1);
- stream_read(s, &hdr[HDR_SIZE - 1], 1);
- }
-
- if (hdr[0] != 'M' || hdr[1] != 'P' || hdr[2] != '+')
- return 0;
- demuxer->movi_start = stream_tell(s) - HDR_SIZE;
- demuxer->movi_end = s->end_pos;
- demuxer->priv = malloc(HDR_SIZE);
- memcpy(demuxer->priv, hdr, HDR_SIZE);
- return DEMUXER_TYPE_MPC;
-}
-
-static demuxer_t *demux_mpc_open(demuxer_t* demuxer) {
- float seconds = 0;
- stream_t *s = demuxer->stream;
- sh_audio_t* sh_audio;
- da_priv_t* priv = demuxer->priv;
-
- sh_audio = new_sh_audio(demuxer,0);
-
- {
- char *wf = calloc(1, sizeof(WAVEFORMATEX) + HDR_SIZE);
- char *header = &wf[sizeof(WAVEFORMATEX)];
- const int freqs[4] = {44100, 48000, 37800, 32000};
- int frames;
- sh_audio->format = mmioFOURCC('M', 'P', 'C', ' ');
- memcpy(header, priv, HDR_SIZE);
- free(priv);
- frames = header[4] | header[5] << 8 | header[6] << 16 | header[7] << 24;
- sh_audio->wf = (WAVEFORMATEX *)wf;
- sh_audio->wf->wFormatTag = sh_audio->format;
- sh_audio->wf->nChannels = 2;
- sh_audio->wf->nSamplesPerSec = freqs[header[10] & 3];
- sh_audio->wf->nBlockAlign = 32 * 36;
- sh_audio->wf->wBitsPerSample = 16;
- seconds = 1152 * frames / (float)sh_audio->wf->nSamplesPerSec;
- if (demuxer->movi_end > demuxer->movi_start && seconds > 1)
- sh_audio->wf->nAvgBytesPerSec = (demuxer->movi_end - demuxer->movi_start) / seconds;
- else
- sh_audio->wf->nAvgBytesPerSec = 32 * 1024; // dummy to make mencoder not hang
- sh_audio->wf->cbSize = HDR_SIZE;
- demuxer->movi_start = stream_tell(s);
- demuxer->movi_end = s->end_pos;
- }
-
- priv = malloc(sizeof(da_priv_t));
- priv->last_pts = -1;
- priv->pts_per_packet = (32 * 36) / (float)sh_audio->wf->nSamplesPerSec;
- priv->length = seconds;
- priv->dword = 0;
- priv->pos = 32; // empty bit buffer
- get_bits(priv, s, 8); // discard first 8 bits
- demuxer->priv = priv;
- demuxer->audio->id = 0;
- demuxer->audio->sh = sh_audio;
- sh_audio->ds = demuxer->audio;
- sh_audio->samplerate = sh_audio->wf->nSamplesPerSec;
- sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;
- sh_audio->audio.dwSampleSize = 0;
- sh_audio->audio.dwScale = 32 * 36;
- sh_audio->audio.dwRate = sh_audio->samplerate;
-
- return demuxer;
-}
-
-static int demux_mpc_fill_buffer(demuxer_t *demux, demux_stream_t *ds) {
- int l;
- int bit_len;
- demux_packet_t* dp;
- sh_audio_t* sh_audio = ds->sh;
- da_priv_t* priv = demux->priv;
- stream_t* s = demux->stream;
- sh_audio = ds->sh;
-
- if (s->eof)
- return 0;
-
- bit_len = get_bits(priv, s, 20);
- dp = new_demux_packet((bit_len + 7) / 8);
- for (l = 0; l < (bit_len / 8); l++)
- dp->buffer[l] = get_bits(priv, s, 8);
- bit_len %= 8;
- if (bit_len)
- dp->buffer[l] = get_bits(priv, s, bit_len) << (8 - bit_len);
- if (priv->last_pts < 0)
- priv->last_pts = 0;
- else
- priv->last_pts += priv->pts_per_packet;
- dp->pts = priv->last_pts;
- ds_add_packet(ds, dp);
- return 1;
-}
-
-static void demux_mpc_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
- sh_audio_t* sh_audio = demuxer->audio->sh;
- da_priv_t* priv = demuxer->priv;
- stream_t* s = demuxer->stream;
- float target = rel_seek_secs;
- if (flags & SEEK_FACTOR)
- target *= priv->length;
- if (!(flags & SEEK_ABSOLUTE))
- target += priv->last_pts;
- if (target < priv->last_pts) {
- stream_seek(s, demuxer->movi_start);
- priv->pos = 32; // empty bit buffer
- get_bits(priv, s, 8); // discard first 8 bits
- priv->last_pts = 0;
- }
- while (target > priv->last_pts) {
- int bit_len = get_bits(priv, s, 20);
- if (bit_len > 32) {
- stream_skip(s, bit_len / 32 * 4 - 4);
- get_bits(priv, s, 32); // make sure dword is reloaded
- }
- get_bits(priv, s, bit_len % 32);
- priv->last_pts += priv->pts_per_packet;
- if (s->eof) break;
- }
- if (!sh_audio) return;
-}
-
-static void demux_close_mpc(demuxer_t* demuxer) {
- da_priv_t* priv = demuxer->priv;
-
- free(priv);
-}
-
-static int demux_mpc_control(demuxer_t *demuxer,int cmd, void *arg){
- da_priv_t* priv = demuxer->priv;
- switch (cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- if (priv->length < 1) return DEMUXER_CTRL_DONTKNOW;
- *((double *)arg) = priv->length;
- return DEMUXER_CTRL_OK;
- case DEMUXER_CTRL_GET_PERCENT_POS:
- if (priv->length < 1) return DEMUXER_CTRL_DONTKNOW;
- *((int *)arg) = priv->last_pts * 100 / priv->length;
- return DEMUXER_CTRL_OK;
- }
- return DEMUXER_CTRL_NOTIMPL;
-}
-
-
-const demuxer_desc_t demuxer_desc_mpc = {
- "Musepack demuxer",
- "mpc",
- "MPC",
- "Reza Jelveh, Reimar Doeffinger",
- "supports v7 bitstream only",
- DEMUXER_TYPE_MPC,
- 0, // unsafe autodetect
- demux_mpc_check,
- demux_mpc_fill_buffer,
- demux_mpc_open,
- demux_close_mpc,
- demux_mpc_seek,
- demux_mpc_control
-};
diff --git a/libmpdemux/demux_mpg.c b/libmpdemux/demux_mpg.c
deleted file mode 100644
index 44ec85d2db..0000000000
--- a/libmpdemux/demux_mpg.c
+++ /dev/null
@@ -1,1248 +0,0 @@
-/*
- * MPG/VOB file parser for DEMUXER v2.5
- * copyright (c) 2001 by A'rpi/ESP-team
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <math.h>
-
-#include "config.h"
-#include "mp_msg.h"
-#include "options.h"
-
-#include "libavutil/attributes.h"
-#include "libmpcodecs/dec_audio.h"
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "parse_es.h"
-#include "stheader.h"
-#include "mp3_hdr.h"
-
-//#define MAX_PS_PACKETSIZE 2048
-#define MAX_PS_PACKETSIZE (224*1024)
-
-#define UNKNOWN 0
-#define VIDEO_MPEG1 0x10000001
-#define VIDEO_MPEG2 0x10000002
-#define VIDEO_MPEG4 0x10000004
-#define VIDEO_H264 0x10000005
-#define AUDIO_MP2 0x50
-#define AUDIO_A52 0x2000
-#define AUDIO_LPCM_BE 0x10001
-#define AUDIO_AAC mmioFOURCC('M', 'P', '4', 'A')
-
-typedef struct mpg_demuxer {
- float last_pts;
- float first_pts; // first pts found in stream
- float first_to_final_pts_len; // difference between final pts and first pts
- int has_valid_timestamps; // !=0 iff time stamps look linear
- // (not necessarily starting with 0)
- unsigned int es_map[0x40]; //es map of stream types (associated to the pes id) from 0xb0 to 0xef
- int num_a_streams;
- int a_stream_ids[MAX_A_STREAMS];
-} mpg_demuxer_t;
-
-static int mpeg_pts_error=0;
-off_t ps_probe = 0;
-
-static int parse_psm(demuxer_t *demux, int len) {
- unsigned char c, id, type;
- unsigned int plen, prog_len, es_map_len;
- mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv;
-
- mp_dbg(MSGT_DEMUX,MSGL_V, "PARSE_PSM, len=%d\n", len);
- if(! len || len > 1018)
- return 0;
-
- c = stream_read_char(demux->stream);
- if(! (c & 0x80)) {
- stream_skip(demux->stream, len - 1); //not yet valid, discard
- return 0;
- }
- stream_skip(demux->stream, 1);
- prog_len = stream_read_word(demux->stream); //length of program descriptors
- stream_skip(demux->stream, prog_len); //.. that we ignore
- es_map_len = stream_read_word(demux->stream); //length of elementary streams map
- es_map_len = FFMIN(es_map_len, len - prog_len - 8); //sanity check
- while(es_map_len > 0) {
- type = stream_read_char(demux->stream);
- id = stream_read_char(demux->stream);
- if(id >= 0xB0 && id <= 0xEF && priv) {
- int idoffset = id - 0xB0;
- switch(type) {
- case 0x1:
- priv->es_map[idoffset] = VIDEO_MPEG1;
- break;
- case 0x2:
- priv->es_map[idoffset] = VIDEO_MPEG2;
- break;
- case 0x3:
- case 0x4:
- priv->es_map[idoffset] = AUDIO_MP2;
- break;
- case 0x0f:
- case 0x11:
- priv->es_map[idoffset] = AUDIO_AAC;
- break;
- case 0x10:
- priv->es_map[idoffset] = VIDEO_MPEG4;
- break;
- case 0x1b:
- priv->es_map[idoffset] = VIDEO_H264;
- break;
- case 0x81:
- priv->es_map[idoffset] = AUDIO_A52;
- break;
- }
- mp_dbg(MSGT_DEMUX,MSGL_V, "PSM ES, id=0x%x, type=%x, stype: %x\n", id, type, priv->es_map[idoffset]);
- }
- plen = stream_read_word(demux->stream); //length of elementary stream descriptors
- plen = FFMIN(plen, es_map_len); //sanity check
- stream_skip(demux->stream, plen); //skip descriptors for now
- es_map_len -= 4 + plen;
- }
- stream_skip(demux->stream, 4); //skip crc32
- return 1;
-}
-
-// 500000 is a wild guess
-#define TIMESTAMP_PROBE_LEN 500000
-
-//MAX_PTS_DIFF_FOR_CONSECUTIVE denotes the maximum difference
-//between two pts to consider them consecutive
-//1.0 is a wild guess
-#define MAX_PTS_DIFF_FOR_CONSECUTIVE 1.0
-
-//returns the first pts found within TIME_STAMP_PROBE_LEN bytes after stream_pos in demuxer's stream.
-//if no pts is found or an error occurs, -1.0 is returned.
-//Packs are freed.
-static float read_first_mpeg_pts_at_position(demuxer_t* demuxer, off_t stream_pos)
-{
- stream_t *s = demuxer->stream;
- mpg_demuxer_t *mpg_d = demuxer->priv;
- float pts = -1.0; //the pts to return;
- float found_pts1; //the most recently found pts
- float found_pts2; //the pts found before found_pts1
- float found_pts3; //the pts found before found_pts2
- int found = 0;
-
- if(!mpg_d || stream_pos < 0)
- return pts;
-
- found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts;
- stream_seek(s, stream_pos);
-
- //We look for pts.
- //However, we do not stop at the first found one, as timestamps may reset
- //Therefore, we seek until we found three consecutive
- //pts within MAX_PTS_DIFF_FOR_CONSECUTIVE.
-
- while(found<3 && !s->eof
- && (fabsf(found_pts2-found_pts1) < MAX_PTS_DIFF_FOR_CONSECUTIVE)
- && (fabsf(found_pts3-found_pts2) < MAX_PTS_DIFF_FOR_CONSECUTIVE)
- && (stream_tell(s) < stream_pos + TIMESTAMP_PROBE_LEN)
- && ds_fill_buffer(demuxer->video))
- {
- if(mpg_d->last_pts != found_pts1)
- {
- if(!found)
- found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts; //the most recently found pts
- else
- {
- found_pts3 = found_pts2;
- found_pts2 = found_pts1;
- found_pts1 = mpg_d->last_pts;
- }
- found++;
- }
- }
-
- if(found == 3) pts = found_pts3;
-
- //clean up from searching of first pts;
- demux_flush(demuxer);
-
- return pts;
-}
-
-/// Open an mpg physical stream
-static demuxer_t* demux_mpg_open(demuxer_t* demuxer) {
- stream_t *s = demuxer->stream;
- mpg_demuxer_t* mpg_d;
-
- if (!ds_fill_buffer(demuxer->video)) return 0;
- mpg_d = calloc(1,sizeof(mpg_demuxer_t));
- if(mpg_d)
- {
- demuxer->priv = mpg_d;
- mpg_d->last_pts = -1.0;
- mpg_d->first_pts = -1.0;
-
- //if seeking is allowed set has_valid_timestamps if appropriate
- if(demuxer->seekable
- && (demuxer->stream->type == STREAMTYPE_FILE
- || demuxer->stream->type == STREAMTYPE_VCD)
- && demuxer->movi_start != demuxer-> movi_end
- )
- {
- //We seek to the beginning of the stream, to somewhere in the
- //middle, and to the end of the stream, while remembering the pts
- //at each of the three positions. With these pts, we check whether
- //or not the pts are "linear enough" to justify seeking by the pts
- //of the stream
-
- //The position where the stream is now
- off_t pos = stream_tell(s);
- float first_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_start);
- if(first_pts != -1.0)
- {
- float middle_pts = read_first_mpeg_pts_at_position(demuxer, (demuxer->movi_end + demuxer->movi_start)/2);
- if(middle_pts != -1.0)
- {
- float final_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_end - TIMESTAMP_PROBE_LEN);
- if(final_pts != -1.0)
- {
- // found proper first, middle, and final pts.
- float proportion = (middle_pts-first_pts==0) ? -1 : (final_pts-middle_pts)/(middle_pts-first_pts);
- // if they are linear enough set has_valid_timestamps
- if((0.5 < proportion) && (proportion < 2))
- {
- mpg_d->first_pts = first_pts;
- mpg_d->first_to_final_pts_len = final_pts - first_pts;
- mpg_d->has_valid_timestamps = 1;
- }
- }
- }
- }
-
- //Cleaning up from seeking in stream
- demuxer->stream->eof=0;
- demuxer->video->eof=0;
- demuxer->audio->eof=0;
-
- stream_seek(s,pos);
- ds_fill_buffer(demuxer->video);
- } // if ( demuxer->seekable )
- } // if ( mpg_d )
- return demuxer;
-}
-
-static void demux_close_mpg(demuxer_t* demuxer) {
- mpg_demuxer_t* mpg_d = demuxer->priv;
- free(mpg_d);
-}
-
-
-static unsigned long long read_mpeg_timestamp(stream_t *s,int c){
- unsigned int d,e;
- unsigned long long pts;
- d=stream_read_word(s);
- e=stream_read_word(s);
- if( ((c&1)!=1) || ((d&1)!=1) || ((e&1)!=1) ){
- ++mpeg_pts_error;
- return 0; // invalid pts
- }
- pts=(((uint64_t)((c>>1)&7))<<30)|((d>>1)<<15)|(e>>1);
- mp_dbg(MSGT_DEMUX,MSGL_DBG3," pts {%llu}",pts);
- return pts;
-}
-
-static void new_audio_stream(demuxer_t *demux, int aid){
- if(!demux->a_streams[aid]){
- mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demux->priv;
- sh_audio_t* sh_a;
- new_sh_audio(demux,aid);
- sh_a = (sh_audio_t*)demux->a_streams[aid];
- sh_a->needs_parsing = 1;
- switch(aid & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id)
- case 0x00: sh_a->format=0x50;break; // mpeg
- case 0xA0: sh_a->format=0x10001;break; // dvd pcm
- case 0x80: if((aid & 0xF8) == 0x88) sh_a->format=0x2001;//dts
- else sh_a->format=0x2000;break; // ac3
- }
- //evo files
- if((aid & 0xC0) == 0xC0) sh_a->format=0x2000;
- else if(aid >= 0x98 && aid <= 0x9f) sh_a->format=0x2001;
- if (mpg_d) mpg_d->a_stream_ids[mpg_d->num_a_streams++] = aid;
- }
- if(demux->audio->id==-1) demux->audio->id=aid;
-}
-
-static int demux_mpg_read_packet(demuxer_t *demux,int id){
- int d av_unused;
- int len;
- int set_pts=0; // !=0 iff pts has been set to a proper value
- unsigned char c=0;
- unsigned long long pts=0;
- unsigned long long dts av_unused = 0;
- int l;
- int pes_ext2_subid=-1;
- double stream_pts = MP_NOPTS_VALUE;
- demux_stream_t *ds=NULL;
- demux_packet_t* dp;
- mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv;
-
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_read_packet: %X\n",id);
-
-// if(id==0x1F0){
-// demux->synced=0; // force resync after 0x1F0
-// return -1;
-//}
-
-// if(id==0x1BA) packet_start_pos=stream_tell(demux->stream);
- if((id<0x1BC || id>=0x1F0) && id != 0x1FD) return -1;
- if(id==0x1BE) return -1; // padding stream
- if(id==0x1BF) return -1; // private2
-
- len=stream_read_word(demux->stream);
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"PACKET len=%d",len);
-// if(len==62480){ demux->synced=0;return -1;} /* :) */
- if(len==0 || len>MAX_PS_PACKETSIZE){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS packet len: %d\n",len);
- return -2; // invalid packet !!!!!!
- }
-
- mpeg_pts_error=0;
-
- if(id==0x1BC) {
- parse_psm(demux, len);
- return 0;
- }
-
- while(len>0){ // Skip stuFFing bytes
- c=stream_read_char(demux->stream);
- --len;
- if(c!=0xFF)break;
- }
- if((c>>6)==1){ // Read (skip) STD scale & size value
-// printf(" STD_scale=%d",(c>>5)&1);
- d=((c&0x1F)<<8)|stream_read_char(demux->stream);
- len-=2;
-// printf(" STD_size=%d",d);
- c=stream_read_char(demux->stream);
- }
- // Read System-1 stream timestamps:
- if((c>>4)==2){
- pts=read_mpeg_timestamp(demux->stream,c);
- set_pts=1;
- len-=4;
- } else
- if((c>>4)==3){
- pts=read_mpeg_timestamp(demux->stream,c);
- c=stream_read_char(demux->stream);
- if((c>>4)!=1) pts=0; //printf("{ERROR4}");
- else set_pts = 1;
- dts=read_mpeg_timestamp(demux->stream,c);
- len-=4+1+4;
- } else
- if((c>>6)==2){
- int pts_flags;
- int hdrlen;
- int parse_ext2;
- // System-2 (.VOB) stream:
- c=stream_read_char(demux->stream);
- pts_flags=c>>6;
- parse_ext2 = (id == 0x1FD) && ((c & 0x3F) == 1);
- c=stream_read_char(demux->stream);
- hdrlen=c;
- len-=2;
- mp_dbg(MSGT_DEMUX,MSGL_DBG3," hdrlen=%d (len=%d)",hdrlen,len);
- if(hdrlen>len){ mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: invalid header length \n"); return -1;}
- if(pts_flags==2 && hdrlen>=5){
- c=stream_read_char(demux->stream);
- pts=read_mpeg_timestamp(demux->stream,c);
- set_pts=1;
- len-=5;hdrlen-=5;
- } else
- if(pts_flags==3 && hdrlen>=10){
- c=stream_read_char(demux->stream);
- pts=read_mpeg_timestamp(demux->stream,c);
- set_pts=1;
- c=stream_read_char(demux->stream);
- dts=read_mpeg_timestamp(demux->stream,c);
- len-=10;hdrlen-=10;
- }
- len-=hdrlen;
- if(parse_ext2 && hdrlen>=3) {
- c=stream_read_char(demux->stream);
- hdrlen--;
-
- if((c & 0x0F) != 0x0F) {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: pes_extension_flag2 not set, discarding pes packet\n");
- return -1;
- }
- if(c & 0x80) { //pes_private_data_flag
- if(hdrlen<16) {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pes_private_data bytes: %d < 16, discarding pes packet\n", hdrlen);
- return -1;
- }
- stream_skip(demux->stream, 16);
- hdrlen-=16;
- }
- if(c & 0x40) { //pack_header_field_flag
- int l = stream_read_char(demux->stream);
- if(l < 0) //couldn't read from the stream?
- return -1;
- hdrlen--;
- if(l < 0 || hdrlen < l) {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pack_header bytes: hdrlen: %d < skip: %d, discarding pes packet\n",
- hdrlen, l);
- return -1;
- }
- stream_skip(demux->stream, l);
- hdrlen-=l;
- }
- if(c & 0x20) { //program_packet_sequence_counter_flag
- if(hdrlen < 2) {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough program_packet bytes: hdrlen: %d, discarding pes packet\n", hdrlen);
- return -1;
- }
- stream_skip(demux->stream, 2);
- hdrlen-=2;
- }
- if(c & 0x10) {
- //STD
- stream_skip(demux->stream, 2);
- hdrlen-=2;
- }
- c=stream_read_char(demux->stream); //pes_extension2 flag
- hdrlen--;
- if(c!=0x81) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown pes_extension2 format, len is > 1 \n"); return -1;}
- c=stream_read_char(demux->stream); //pes_extension2 payload === substream id
- hdrlen--;
- if(c<0x55 || c>0x5F) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown vc1 substream_id: 0x%x \n", c); return -1;}
- pes_ext2_subid=c;
- }
- if(hdrlen>0)
- stream_skip(demux->stream,hdrlen); // skip header and stuffing bytes
-
- if(id==0x1FD && pes_ext2_subid!=-1) {
- //==== EVO VC1 STREAMS ===//
- if(!demux->v_streams[pes_ext2_subid]) new_sh_video(demux,pes_ext2_subid);
- if(demux->video->id==-1) demux->video->id=pes_ext2_subid;
- if(demux->video->id==pes_ext2_subid){
- ds=demux->video;
- if(!ds->sh) ds->sh=demux->v_streams[pes_ext2_subid];
- if(priv && ds->sh) {
- sh_video_t *sh = (sh_video_t *)ds->sh;
- sh->format = mmioFOURCC('W', 'V', 'C', '1');
- }
- }
- }
- //============== DVD Audio sub-stream ======================
- if(id==0x1BD){
- int aid, rawa52 = 0;
- off_t tmppos;
- unsigned int tmp;
-
- tmppos = stream_tell(demux->stream);
- tmp = stream_read_word(demux->stream);
- stream_seek(demux->stream, tmppos);
- /// vdr stores A52 without the 4 header bytes, so we have to check this condition first
- if(tmp == 0x0B77) {
- aid = 128;
- rawa52 = 1;
- }
- else {
- aid=stream_read_char(demux->stream);--len;
- if(len<3) return -1; // invalid audio packet
- }
-
- // AID:
- // 0x20..0x3F subtitle
- // 0x80..0x87 and 0xC0..0xCF AC3 audio
- // 0x88..0x8F and 0x98..0x9F DTS audio
- // 0xA0..0xBF PCM audio
-
- if((aid & 0xE0) == 0x20){
- // subtitle:
- aid&=0x1F;
-
- if(!demux->s_streams[aid]){
- sh_sub_t *sh = new_sh_sub(demux, aid);
- if (sh) sh->type = 'v';
- mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid);
- }
-
- if(demux->sub->id > -1)
- demux->sub->id &= 0x1F;
- if(!demux->opts->sub_lang && demux->sub->id == -1)
- demux->sub->id = aid;
- if(demux->sub->id==aid){
- ds=demux->sub;
- }
- } else if((aid >= 0x80 && aid <= 0x8F) || (aid >= 0x98 && aid <= 0xAF) || (aid >= 0xC0 && aid <= 0xCF)) {
-
-// aid=128+(aid&0x7F);
- // aid=0x80..0xBF
- new_audio_stream(demux, aid);
- if(demux->audio->id==aid){
- int type;
- ds=demux->audio;
- if(!ds->sh) ds->sh=demux->a_streams[aid];
- // READ Packet: Skip additional audio header data:
- if(!rawa52) {
- c=stream_read_char(demux->stream);//num of frames
- type=stream_read_char(demux->stream);//startpos hi
- type=(type<<8)|stream_read_char(demux->stream);//startpos lo
-// printf("\r[%02X][%04X]",c,type);
- len-=3;
- }
- if((aid&0xE0)==0xA0 && len>=3){
- unsigned char* hdr;
- // save audio header as codecdata!
- if(!((sh_audio_t*)(ds->sh))->codecdata_len){
- ((sh_audio_t*)(ds->sh))->codecdata=malloc(3);
- ((sh_audio_t*)(ds->sh))->codecdata_len=3;
- }
- hdr=((sh_audio_t*)(ds->sh))->codecdata;
- // read LPCM header:
- // emphasis[1], mute[1], rvd[1], frame number[5]:
- hdr[0]=stream_read_char(demux->stream);
-// printf(" [%01X:%02d]",c>>5,c&31);
- // quantization[2],freq[2],rvd[1],channels[3]
- hdr[1]=stream_read_char(demux->stream);
-// printf("[%01X:%01X] ",c>>4,c&15);
- // dynamic range control (0x80=off):
- hdr[2]=stream_read_char(demux->stream);
-// printf("[%02X] ",c);
- len-=3;
- if(len<=0) mp_msg(MSGT_DEMUX,MSGL_V,"End of packet while searching for PCM header\n");
- }
-// printf(" \n");
- } // if(demux->audio->id==aid)
-
- } else mp_msg(MSGT_DEMUX,MSGL_V,"Unknown 0x1BD substream: 0x%02X \n",aid);
- } //if(id==0x1BD)
- } else {
- if(c!=0x0f){
- mp_msg(MSGT_DEMUX,MSGL_V," {ERROR5,c=%d} \n",c);
- return -1; // invalid packet !!!!!!
- }
- }
- if(mpeg_pts_error) mp_msg(MSGT_DEMUX,MSGL_V," {PTS_err:%d} \n",mpeg_pts_error);
- mp_dbg(MSGT_DEMUX,MSGL_DBG3," => len=%d\n",len);
-
-// if(len<=0 || len>MAX_PS_PACKETSIZE) return -1; // Invalid packet size
- if(len<=0 || len>MAX_PS_PACKETSIZE){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS data len: %d\n",len);
- return -1; // invalid packet !!!!!!
- }
-
- if(id>=0x1C0 && id<=0x1DF){
- // mpeg audio
- int aid=id-0x1C0;
- new_audio_stream(demux, aid);
- if(demux->audio->id==aid){
- ds=demux->audio;
- if(!ds->sh) ds->sh=demux->a_streams[aid];
- if(priv && ds->sh) {
- sh_audio_t *sh = (sh_audio_t *)ds->sh;
- if(priv->es_map[id - 0x1B0])
- sh->format = priv->es_map[id - 0x1B0];
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
- }
- }
- } else
- if(id>=0x1E0 && id<=0x1EF){
- // mpeg video
- int aid=id-0x1E0;
- if(!demux->v_streams[aid]) new_sh_video(demux,aid);
- if(demux->video->id==-1) demux->video->id=aid;
- if(demux->video->id==aid){
- ds=demux->video;
- if(!ds->sh) ds->sh=demux->v_streams[aid];
- if(priv && ds->sh) {
- sh_video_t *sh = (sh_video_t *)ds->sh;
- if(priv->es_map[id - 0x1B0]) {
- sh->format = priv->es_map[id - 0x1B0];
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
- }
- }
- }
- }
-
- if(ds){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Read %d data bytes from packet %04X\n",len,id);
-// printf("packet start = 0x%X \n",stream_tell(demux->stream)-packet_start_pos);
-
- dp=new_demux_packet(len);
- if(!dp) {
- mp_dbg(MSGT_DEMUX,MSGL_ERR,"DEMUX_MPG ERROR: couldn't create demux_packet(%d bytes)\n",len);
- stream_skip(demux->stream,len);
- return 0;
- }
- l = stream_read(demux->stream,dp->buffer,len);
- if(l<len)
- resize_demux_packet(dp, l);
- len = l;
- if(set_pts)
- dp->pts=pts/90000.0f;
- dp->pos=demux->filepos;
- /*
- workaround:
- set dp->stream_pts only when feeding the video stream, or strangely interleaved files
- (such as SWIII) will show strange alternations in the stream time, wildly going
- back and forth
- */
- if(ds == demux->video && stream_control(demux->stream, STREAM_CTRL_GET_CURRENT_TIME,(void *)&stream_pts)!=STREAM_UNSUPPORTED)
- dp->stream_pts = stream_pts;
- ds_add_packet(ds,dp);
- if (demux->priv && set_pts) ((mpg_demuxer_t*)demux->priv)->last_pts = pts/90000.0f;
-// if(ds==demux->sub) parse_dvdsub(ds->last->buffer,ds->last->len);
- return 1;
- }
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Skipping %d data bytes from packet %04X\n",len,id);
- if(len<=2356) stream_skip(demux->stream,len);
- return 0;
-}
-
-static int num_elementary_packets100=0;
-static int num_elementary_packets101=0;
-static int num_elementary_packets12x=0;
-static int num_elementary_packets1B6=0;
-static int num_elementary_packetsPES=0;
-static int num_mpeg12_startcode=0;
-static int num_h264_slice=0; //combined slice
-static int num_h264_dpa=0; //DPA Slice
-static int num_h264_dpb=0; //DPB Slice
-static int num_h264_dpc=0; //DPC Slice
-static int num_h264_idr=0; //IDR Slice
-static int num_h264_sps=0;
-static int num_h264_pps=0;
-
-static int num_mp3audio_packets=0;
-
-static void clear_stats(void)
-{
- num_elementary_packets100=0;
- num_elementary_packets101=0;
- num_elementary_packets1B6=0;
- num_elementary_packets12x=0;
- num_elementary_packetsPES=0;
- num_mpeg12_startcode=0;
- num_h264_slice=0; //combined slice
- num_h264_dpa=0; //DPA Slice
- num_h264_dpb=0; //DPB Slice
- num_h264_dpc=0; //DPC Slice
- num_h264_idr=0; //IDR Slice
- num_h264_sps=0;
- num_h264_pps=0;
- num_mp3audio_packets=0;
-}
-
-//assumes demuxer->synced < 2
-static inline void update_stats(int head)
-{
- if(head==0x1B6) ++num_elementary_packets1B6;
- else if(head==0x1B3 || head==0x1B8) ++num_mpeg12_startcode;
- else if(head==0x100) ++num_elementary_packets100;
- else if(head==0x101) ++num_elementary_packets101;
- else if(head==0x1BD || (0x1C0<=head && head<=0x1EF))
- num_elementary_packetsPES++;
- else if(head>=0x120 && head<=0x12F) ++num_elementary_packets12x;
- if(head>=0x100 && head<0x1B0)
- {
- if((head&~0x60) == 0x101) ++num_h264_slice;
- else if((head&~0x60) == 0x102) ++num_h264_dpa;
- else if((head&~0x60) == 0x103) ++num_h264_dpb;
- else if((head&~0x60) == 0x104) ++num_h264_dpc;
- else if((head&~0x60) == 0x105 && head != 0x105) ++num_h264_idr;
- else if((head&~0x60) == 0x107 && head != 0x107) ++num_h264_sps;
- else if((head&~0x60) == 0x108 && head != 0x108) ++num_h264_pps;
- }
-}
-
-static int demux_mpg_probe(demuxer_t *demuxer) {
- int pes av_unused = 1;
- int tmp;
- off_t tmppos;
- int file_format = DEMUXER_TYPE_UNKNOWN;
-
- tmppos=stream_tell(demuxer->stream);
- tmp=stream_read_dword(demuxer->stream);
- if(tmp==0x1E0 || tmp==0x1C0) {
- tmp=stream_read_word(demuxer->stream);
- if(tmp>1 && tmp<=2048) pes=0; // demuxer->synced=3; // PES...
- }
- stream_seek(demuxer->stream,tmppos);
-
- clear_stats();
-
- if(demux_mpg_open(demuxer))
- file_format=DEMUXER_TYPE_MPEG_PS;
- else {
- mp_msg(MSGT_DEMUX,MSGL_V,"MPEG packet stats: p100: %d p101: %d p1B6: %d p12x: %d sli: %d a: %d b: %d c: %d idr: %d sps: %d pps: %d PES: %d MP3: %d, synced: %d\n",
- num_elementary_packets100,num_elementary_packets101,
- num_elementary_packets1B6,num_elementary_packets12x,
- num_h264_slice, num_h264_dpa,
- num_h264_dpb, num_h264_dpc=0,
- num_h264_idr, num_h264_sps=0,
- num_h264_pps,
- num_elementary_packetsPES,num_mp3audio_packets, demuxer->synced);
-
- //MPEG packet stats: p100: 458 p101: 458 PES: 0 MP3: 1103 (.m2v)
- if(num_mp3audio_packets>50 && num_mp3audio_packets>2*num_elementary_packets100
- && abs(num_elementary_packets100-num_elementary_packets101)>2)
- return file_format;
-
- // some hack to get meaningfull error messages to our unhappy users:
- if(num_mpeg12_startcode>=2 && num_elementary_packets100>=2 && num_elementary_packets101>=2 &&
- abs(num_elementary_packets101+8-num_elementary_packets100)<16) {
- if(num_elementary_packetsPES>=4 && num_elementary_packetsPES>=num_elementary_packets100-4) {
- return file_format;
- }
- file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :)
- } else
- // fuzzy mpeg4-es detection. do NOT enable without heavy testing of mpeg formats detection!
- if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 &&
- num_elementary_packetsPES==0 && num_elementary_packets100<=num_elementary_packets12x &&
- demuxer->synced<2) {
- file_format=DEMUXER_TYPE_MPEG4_ES;
- } else
- // fuzzy h264-es detection. do NOT enable without heavy testing of mpeg formats detection!
- if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) &&
- /* FIXME num_h264_sps>=1 && */ num_h264_pps>=1 && num_h264_idr>=1 &&
- num_elementary_packets1B6==0 && num_elementary_packetsPES==0 &&
- demuxer->synced<2) {
- file_format=DEMUXER_TYPE_H264_ES;
- } else
- {
- if(demuxer->synced==2)
- mp_msg(MSGT_DEMUXER, MSGL_ERR, "MPEG: %s",
- mp_gtext("Missing video stream!? Contact the author, it may be a bug :(\n"));
- else
- mp_tmsg(MSGT_DEMUXER,MSGL_V,"Not MPEG System Stream format... (maybe Transport Stream?)\n");
- }
- }
- //FIXME this shouldn't be necessary
- stream_seek(demuxer->stream,tmppos);
- return file_format;
-}
-
-static int demux_mpg_es_fill_buffer(demuxer_t *demux, demux_stream_t *ds){
- // Elementary video stream
- if(demux->stream->eof) return 0;
- demux->filepos=stream_tell(demux->stream);
- ds_read_packet(demux->video,demux->stream,STREAM_BUFFER_SIZE,0,demux->filepos,0);
- return 1;
-}
-
-/**
- * \brief discard until 0x100 header and return a filled buffer
- * \param b buffer-end pointer
- * \param pos current pos in stream, negative since b points to end of buffer
- * \param s stream to read from
- * \return new position, differs from original pos when eof hit and thus
- * b was modified to point to the new end of buffer
- */
-static int find_end(unsigned char **b, int pos, stream_t *s) {
- register int state = 0xffffffff;
- unsigned char *buf = *b;
- int start = pos;
- int read, unused;
- // search already read part
- while (state != 0x100 && pos) {
- state = state << 8 | buf[pos++];
- }
- // continue search in stream
- while (state != 0x100) {
- register int c = stream_read_char(s);
- if (c < 0) break;
- state = state << 8 | c;
- }
- // modify previous header (from 0x1bc or 0x1bf to 0x100)
- buf[start++] = 0;
- // copy remaining buffer part to current pos
- memmove(&buf[start], &buf[pos], -pos);
- unused = start + -pos; // -unused bytes in buffer
- read = stream_read(s, &buf[unused], -unused);
- unused += read;
- // fix buffer so it ends at pos == 0 (eof case)
- *b = &buf[unused];
- start -= unused;
- return start;
-}
-
-/**
- * This format usually uses an insane bitrate, which makes this function
- * performance-critical!
- * Be sure to benchmark any changes with different compiler versions.
- */
-static int demux_mpg_gxf_fill_buffer(demuxer_t *demux, demux_stream_t *ds) {
- demux_packet_t *pack;
- int len;
- demux->filepos = stream_tell(demux->stream);
- pack = new_demux_packet(STREAM_BUFFER_SIZE);
- len = stream_read(demux->stream, pack->buffer, STREAM_BUFFER_SIZE);
- if (len <= 0)
- {
- free_demux_packet(pack);
- return 0;
- }
- {
- register uint32_t state = (uint32_t)demux->priv;
- register int pos = -len;
- unsigned char *buf = &pack->buffer[len];
- do {
- state = state << 8 | buf[pos];
- if (unlikely((state | 3) == 0x1bf))
- pos = find_end(&buf, pos, demux->stream);
- } while (++pos < 0);
- demux->priv = (void *)state;
- len = buf - pack->buffer;
- }
- if (len < STREAM_BUFFER_SIZE)
- resize_demux_packet(pack, len);
- ds_add_packet(ds, pack);
- return 1;
-}
-
-static int demux_mpg_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
-{
-unsigned int head=0;
-int skipped=0;
-int max_packs=256; // 512kbyte
-int ret=0;
-
-// System stream
-do{
- demux->filepos=stream_tell(demux->stream);
- //lame workaround: this is needed to show the progress bar when playing dvdnav://
- //(ths poor guy doesn't know teh length of the stream at startup)
- demux->movi_end = demux->stream->end_pos;
- head=stream_read_dword(demux->stream);
- if((head&0xFFFFFF00)!=0x100){
- // sync...
- demux->filepos-=skipped;
- while(1){
- int c=stream_read_char(demux->stream);
- if(c<0) break; //EOF
- head<<=8;
- if(head!=0x100){
- head|=c;
- if(mp_check_mp3_header(head)) ++num_mp3audio_packets;
- ++skipped; //++demux->filepos;
- continue;
- }
- head|=c;
- break;
- }
- demux->filepos+=skipped;
- }
- if(stream_eof(demux->stream)) break;
- // sure: head=0x000001XX
- mp_dbg(MSGT_DEMUX,MSGL_DBG4,"*** head=0x%X\n",head);
- if(demux->synced==0){
- if(head==0x1BA) demux->synced=1; //else
-// if(head==0x1BD || (head>=0x1C0 && head<=0x1EF)) demux->synced=3; // PES?
- } else
- if(demux->synced==1){
- if(head==0x1BB || head==0x1BD || (head>=0x1C0 && head<=0x1EF)){
- demux->synced=2;
- mp_msg(MSGT_DEMUX,MSGL_V,"system stream synced at 0x%"PRIX64" (%"PRId64")!\n",(int64_t)demux->filepos,(int64_t)demux->filepos);
- num_elementary_packets100=0; // requires for re-sync!
- num_elementary_packets101=0; // requires for re-sync!
- } else demux->synced=0;
- } // else
- if(demux->synced>=2){
- ret=demux_mpg_read_packet(demux,head);
- if(!ret)
- if(--max_packs==0){
- demux->stream->eof=1;
- mp_tmsg(MSGT_DEMUX,MSGL_ERR,"demux: File doesn't contain the selected audio or video stream.\n");
- return 0;
- }
- if(demux->synced==3) demux->synced=(ret==1)?2:0; // PES detect
- } else {
- update_stats(head);
- if(head>=0x100 && head<0x1B0)
- mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... elementary video packet found: %03X\n",head);
- else if((head>=0x1C0 && head<0x1F0) || head==0x1BD)
- mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... PES packet found: %03X\n",head);
-
- if(((num_elementary_packets100>50 && num_elementary_packets101>50) ||
- (num_elementary_packetsPES>50)) && skipped>4000000){
- mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be ES/PES stream...\n");
- demux->stream->eof=1;
- break;
- }
- if(num_mp3audio_packets>100 && num_elementary_packets100<10){
- mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be MP3 stream...\n");
- demux->stream->eof=1;
- break;
- }
- }
-} while(ret!=1);
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"demux: %d bad bytes skipped\n",skipped);
- if(demux->stream->eof){
- mp_msg(MSGT_DEMUX,MSGL_V,"MPEG Stream reached EOF\n");
- return 0;
- }
- return 1;
-}
-
-static void demux_seek_mpg(demuxer_t *demuxer, float rel_seek_secs,
- float audio_delay, int flags)
-{
- demux_stream_t *d_audio=demuxer->audio;
- demux_stream_t *d_video=demuxer->video;
- sh_audio_t *sh_audio=d_audio->sh;
- sh_video_t *sh_video=d_video->sh;
- mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
- int precision = 1;
- float oldpts = 0;
- off_t oldpos = demuxer->filepos;
- float newpts = 0;
- off_t newpos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : oldpos;
-
- if(mpg_d)
- oldpts = mpg_d->last_pts;
- newpts = (flags & SEEK_ABSOLUTE) ? 0.0 : oldpts;
- //================= seek in MPEG ==========================
- //calculate the pts to seek to
- if(flags & SEEK_FACTOR) {
- if (mpg_d && mpg_d->first_to_final_pts_len > 0.0)
- newpts += mpg_d->first_to_final_pts_len * rel_seek_secs;
- else
- newpts += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * oldpts / oldpos;
- } else
- newpts += rel_seek_secs;
- if (newpts < 0) newpts = 0;
-
- if(flags&SEEK_FACTOR){
- // float seek 0..1
- newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs;
- } else {
- // time seek (secs)
- if (mpg_d && mpg_d->has_valid_timestamps) {
- if (mpg_d->first_to_final_pts_len > 0.0)
- newpos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / mpg_d->first_to_final_pts_len;
- else if (oldpts > 0.0)
- newpos += rel_seek_secs * (oldpos - demuxer->movi_start) / oldpts;
- } else if(!sh_video || !sh_video->i_bps) // unspecified or VBR
- newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec
- else
- newpos+=sh_video->i_bps*rel_seek_secs;
- }
-
- while (1) {
- if(newpos<demuxer->movi_start){
- if(demuxer->stream->type!=STREAMTYPE_VCD) demuxer->movi_start=0; // for VCD
- if(newpos<demuxer->movi_start) newpos=demuxer->movi_start;
- }
-
- stream_seek(demuxer->stream,newpos);
-
- // re-sync video:
- videobuf_code_len=0; // reset ES stream buffer
-
- ds_fill_buffer(d_video);
- if(sh_audio){
- ds_fill_buffer(d_audio);
- }
-
- while(1){
- int i;
- if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts){
- float a_pts=d_audio->pts;
- a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
- if(d_video->pts>a_pts){
- skip_audio_frame(sh_audio); // sync audio
- continue;
- }
- }
- if(!sh_video) break;
- i=sync_video_packet(d_video);
- if(sh_video->format == mmioFOURCC('W', 'V', 'C', '1')) {
- if(i==0x10E || i==0x10F) //entry point or sequence header
- break;
- } else
- if(sh_video->format == 0x10000004) { //mpeg4
- if(i==0x1B6) { //vop (frame) startcode
- int pos = videobuf_len;
- if(!read_video_packet(d_video)) break; // EOF
- if((videobuffer[pos+4] & 0x3F) == 0) break; //I-frame
- }
- } else if(sh_video->format == 0x10000005){ //h264
- if((i & ~0x60) == 0x105) break;
- } else { //default mpeg1/2
- if(i==0x1B3 || i==0x1B8) break; // found it!
- }
- if(!i || !skip_video_packet(d_video)) break; // EOF?
- }
- if(!mpg_d)
- break;
- if (!precision || abs(newpts - mpg_d->last_pts) < 0.5 || (mpg_d->last_pts == oldpts)) break;
- if ((newpos - oldpos) * (mpg_d->last_pts - oldpts) < 0) { // invalid timestamps
- mpg_d->has_valid_timestamps = 0;
- break;
- }
- precision--;
- //prepare another seek because we are off by more than 0.5s
- if(mpg_d) {
- newpos += (newpts - mpg_d->last_pts) * (newpos - oldpos) / (mpg_d->last_pts - oldpts);
- demux_flush(demuxer);
- demuxer->stream->eof=0; // clear eof flag
- d_video->eof=0;
- d_audio->eof=0;
- }
- }
-}
-
-static int demux_mpg_control(demuxer_t *demuxer, int cmd, void *arg)
-{
- mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
-
- switch(cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- if(stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, arg) != STREAM_UNSUPPORTED) {
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\r\nDEMUX_MPG_CTRL, (%.3f)\r\n", *((double*)arg));
- return DEMUXER_CTRL_GUESS;
- }
- if (mpg_d && mpg_d->has_valid_timestamps) {
- *((double *)arg)=(double)mpg_d->first_to_final_pts_len;
- return DEMUXER_CTRL_OK;
- }
- return DEMUXER_CTRL_DONTKNOW;
-
- case DEMUXER_CTRL_GET_PERCENT_POS:
- if (mpg_d && mpg_d->has_valid_timestamps && mpg_d->first_to_final_pts_len > 0.0) {
- *((int *)arg)=(int)(100 * (mpg_d->last_pts-mpg_d->first_pts) / mpg_d->first_to_final_pts_len);
- return DEMUXER_CTRL_OK;
- }
- return DEMUXER_CTRL_DONTKNOW;
-
- case DEMUXER_CTRL_SWITCH_AUDIO:
- if(! (mpg_d && mpg_d->num_a_streams > 1 && demuxer->audio && demuxer->audio->sh))
- return DEMUXER_CTRL_NOTIMPL;
- else {
- demux_stream_t *d_audio = demuxer->audio;
- sh_audio_t *sh_audio = d_audio->sh;
- sh_audio_t *sh_a = sh_audio;
- int i;
- if(!sh_audio)
- return DEMUXER_CTRL_NOTIMPL;
- if (*((int*)arg) < 0)
- {
- for (i = 0; i < mpg_d->num_a_streams; i++) {
- if (d_audio->id == mpg_d->a_stream_ids[i]) break;
- }
- i = (i+1) % mpg_d->num_a_streams;
- sh_a = (sh_audio_t*)demuxer->a_streams[mpg_d->a_stream_ids[i]];
- }
- else {
- for (i = 0; i < mpg_d->num_a_streams; i++)
- if (*((int*)arg) == mpg_d->a_stream_ids[i]) break;
- if (i < mpg_d->num_a_streams)
- sh_a = (sh_audio_t*)demuxer->a_streams[*((int*)arg)];
- }
- if (i < mpg_d->num_a_streams && d_audio->id != mpg_d->a_stream_ids[i]) {
- d_audio->id = mpg_d->a_stream_ids[i];
- d_audio->sh = sh_a;
- ds_free_packs(d_audio);
- }
- }
- *((int*)arg) = demuxer->audio->id;
- return DEMUXER_CTRL_OK;
-
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-
-static int demux_mpg_pes_probe(demuxer_t *demuxer) {
- demuxer->synced = 3;
- return (demux_mpg_probe(demuxer) == DEMUXER_TYPE_MPEG_PS) ? DEMUXER_TYPE_MPEG_PES : 0;
-}
-
-
-static demuxer_t* demux_mpg_es_open(demuxer_t* demuxer)
-{
- sh_video_t *sh_video=NULL;
-
- demuxer->audio->sh = NULL; // ES streams has no audio channel
- demuxer->video->sh = new_sh_video(demuxer,0); // create dummy video stream header, id=0
- sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
-
- return demuxer;
-}
-
-static demuxer_t *demux_mpg_gxf_open(demuxer_t *demuxer) {
- demuxer->audio->sh = NULL;
- demuxer->video->sh = new_sh_video(demuxer,0);
- ((sh_video_t *)demuxer->video->sh)->ds = demuxer->video;
- demuxer->priv = (void *) 0xffffffff;
- return demuxer;
-}
-
-static demuxer_t* demux_mpg_ps_open(demuxer_t* demuxer)
-{
- sh_audio_t *sh_audio=NULL;
- sh_video_t *sh_video=NULL;
-
- sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
-
- if(demuxer->audio->id!=-2) {
- if(!ds_fill_buffer(demuxer->audio)){
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "MPEG: %s",
- mp_gtext("No audio stream found -> no sound.\n"));
- demuxer->audio->sh=NULL;
- } else {
- sh_audio=demuxer->audio->sh;sh_audio->ds=demuxer->audio;
- }
- }
-
- if(!sh_video->format && ps_probe > 0) {
- int head;
- off_t pos = stream_tell(demuxer->stream);
-
- clear_stats();
- do {
- head=sync_video_packet(demuxer->video);
- if(!head) break;
- update_stats(head);
- skip_video_packet(demuxer->video);
- } while(stream_tell(demuxer->stream) < pos + ps_probe && !demuxer->stream->eof);
-
- ds_free_packs(demuxer->video);
- demuxer->stream->eof=0;
- stream_seek(demuxer->stream, pos);
- mp_msg(MSGT_DEMUX,MSGL_INFO,"MPEG packet stats: p100: %d p101: %d p1B6: %d p12x: %d sli: %d a: %d b: %d c: %d idr: %d sps: %d pps: %d\n",
- num_elementary_packets100, num_elementary_packets101,
- num_elementary_packets1B6, num_elementary_packets12x,
- num_h264_slice, num_h264_dpa, num_h264_dpb, num_h264_dpc,
- num_h264_idr, num_h264_sps, num_h264_pps);
-
- if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 &&
- num_elementary_packets100<=num_elementary_packets12x)
- sh_video->format = 0x10000004;
- else if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) &&
- num_h264_sps>=1 && num_h264_pps>=1 && num_h264_idr>=1 &&
- num_elementary_packets1B6==0)
- sh_video->format = 0x10000005;
- else sh_video->format = 0x10000002;
- }
-
- return demuxer;
-}
-
-
-const demuxer_desc_t demuxer_desc_mpeg_ps = {
- "MPEG PS demuxer",
- "mpegps",
- "MPEG-PS",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_MPEG_PS,
- 0, // unsafe autodetect
- demux_mpg_probe,
- demux_mpg_fill_buffer,
- demux_mpg_ps_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
-
-
-const demuxer_desc_t demuxer_desc_mpeg_pes = {
- "MPEG PES demuxer",
- "mpegpes",
- "MPEG-PES",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_MPEG_PES,
- 0, // unsafe autodetect
- demux_mpg_pes_probe,
- demux_mpg_fill_buffer,
- demux_mpg_ps_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
-
-
-const demuxer_desc_t demuxer_desc_mpeg_gxf = {
- "MPEG ES in GXF demuxer",
- "mpeggxf",
- "MPEG-ES in GXF",
- "Reimar Doeffinger",
- "Mpeg",
- DEMUXER_TYPE_MPEG_GXF,
- 0, // hack autodetection
- NULL,
- demux_mpg_gxf_fill_buffer,
- demux_mpg_gxf_open,
- NULL,
- NULL,
- NULL
-};
-
-const demuxer_desc_t demuxer_desc_mpeg_es = {
- "MPEG ES demuxer",
- "mpeges",
- "MPEG-ES",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_MPEG_ES,
- 0, // hack autodetection
- NULL,
- demux_mpg_es_fill_buffer,
- demux_mpg_es_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
-
-
-const demuxer_desc_t demuxer_desc_mpeg4_es = {
- "MPEG4 ES demuxer",
- "mpeg4es",
- "MPEG-ES",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_MPEG4_ES,
- 0, // hack autodetection
- NULL,
- demux_mpg_es_fill_buffer,
- demux_mpg_es_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
-
-
-const demuxer_desc_t demuxer_desc_h264_es = {
- "H.264 ES demuxer",
- "h264es",
- "H264-ES",
- "Arpi?",
- "Mpeg",
- DEMUXER_TYPE_H264_ES,
- 0, // hack autodetection
- NULL,
- demux_mpg_es_fill_buffer,
- demux_mpg_es_open,
- demux_close_mpg,
- demux_seek_mpg,
- demux_mpg_control,
-};
diff --git a/libmpdemux/demux_nsv.c b/libmpdemux/demux_nsv.c
deleted file mode 100644
index 9ab68dd894..0000000000
--- a/libmpdemux/demux_nsv.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Nullsoft Streaming Video demuxer
- * copyright (c) 2004 by Reza Jelveh <reza.jelveh@tuhh.de>
- * Based on A'rpis G2 work
- *
- * seeking and PCM audio not yet supported
- * PCM needs extra audio chunk "miniheader" parsing
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "mp_msg.h"
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-typedef struct {
- float v_pts;
- int video_pack_no;
- unsigned int a_format;
- unsigned int v_format;
- unsigned char fps;
-} nsv_priv_t;
-
-#define HEADER_SEARCH_SIZE 256000
-
-
-/**
- * Seeking still to be implemented
- */
-static void demux_seek_nsv ( demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags )
-{
-// seeking is not yet implemented
-}
-
-
-static int demux_nsv_fill_buffer ( demuxer_t *demuxer, demux_stream_t *ds )
-{
- unsigned char hdr[17];
- // for the extra data
- unsigned char aux[6];
- int i_aux = 0;
- // videolen = audio chunk length, audiolen = video chunk length
- int videolen,audiolen;
-
- sh_video_t *sh_video = demuxer->video->sh;
- sh_audio_t *sh_audio = demuxer->audio->sh;
-
- nsv_priv_t * priv = demuxer->priv;
-
- // if the audio/video chunk has no new header the first 2 bytes will be discarded 0xBEEF
- // or rather 0xEF 0xBE
- stream_read(demuxer->stream,hdr,7);
- if(stream_eof(demuxer->stream)) return 0;
- // sometimes instead of 0xBEEF as described for the next audio/video chunk we get
- // a whole new header
-
- mp_dbg(MSGT_DEMUX, MSGL_DBG2, "demux_nsv: %08X %08X\n",
- hdr[0]<<8|hdr[1], (unsigned int)stream_tell(demuxer->stream));
- switch(hdr[0]<<8|hdr[1]) {
- case 0x4E53:
- if(hdr[2]==0x56 && hdr[3]==0x73){
- // NSVs
- // get the header since there is no more metaheader after the first one
- // there is no more need to skip that
- stream_read(demuxer->stream,hdr+7,17-7);
- stream_read(demuxer->stream,hdr,7);
- }
- break;
-
- case 0xEFBE:
- break;
-
- default:
- mp_dbg(MSGT_DEMUX,MSGL_WARN,"demux_nsv: sync lost\n");
- break;
- }
-
- if (sh_video)
- priv->v_pts =demuxer->video->pts= priv->video_pack_no *
- (float)sh_video->frametime;
- else
- priv->v_pts = priv->video_pack_no;
-
- demuxer->filepos=stream_tell(demuxer->stream);
-
-
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"demux_nsv: %08X: %02X %02X | %02X %02X %02X | %02X %02X \n",
- (int)demuxer->filepos, hdr[0],hdr[1],hdr[2],hdr[3],hdr[4],hdr[5],hdr[6]);
-
- // read video:
- videolen=(hdr[2]>>4)|(hdr[3]<<4)|(hdr[4]<<0xC);
- //check if we got extra data like subtitles here
- if( (hdr[2]&0x0f) != 0x0 ) {
- stream_read( demuxer->stream, aux, 6);
-
- i_aux = aux[0]|aux[1]<<8;
- // We skip this extra data
- stream_skip( demuxer->stream, i_aux );
- i_aux+=6;
- videolen -= i_aux;
- }
-
-
- // we need to return an empty packet when the
- // video frame is empty otherwise the stream will fasten up
- if(sh_video) {
- if( (hdr[2]&0x0f) != 0x0 )
- ds_read_packet(demuxer->video,demuxer->stream,videolen,priv->v_pts,demuxer->filepos-i_aux,0);
- else
- ds_read_packet(demuxer->video,demuxer->stream,videolen,priv->v_pts,demuxer->filepos,0);
- }
- else
- stream_skip(demuxer->stream,videolen);
-
- // read audio:
- audiolen=(hdr[5])|(hdr[6]<<8);
- // we need to return an empty packet when the
- // audio frame is empty otherwise the stream will fasten up
- if(sh_audio) {
- ds_read_packet(demuxer->audio,demuxer->stream,audiolen,priv->v_pts,demuxer->filepos+videolen,0);
- }
- else
- stream_skip(demuxer->stream,audiolen);
-
- ++priv->video_pack_no;
-
- return 1;
-
-}
-
-
-static demuxer_t* demux_open_nsv ( demuxer_t* demuxer )
-{
- // last 2 bytes 17 and 18 are unknown but right after that comes the length
- unsigned char hdr[17];
- int videolen,audiolen;
- unsigned char buf[10];
- sh_video_t *sh_video = NULL;
- sh_audio_t *sh_audio = NULL;
-
-
- nsv_priv_t * priv = malloc(sizeof(nsv_priv_t));
- demuxer->priv=priv;
- priv->video_pack_no=0;
-
- /* disable seeking yet to be fixed*/
- demuxer->seekable = 0;
-
- stream_read(demuxer->stream,hdr,4);
- if(stream_eof(demuxer->stream)) return 0;
-
- if(hdr[0]==0x4E && hdr[1]==0x53 && hdr[2]==0x56){
- // NSV header!
- if(hdr[3]==0x73){
- // NSVs
- stream_read(demuxer->stream,hdr+4,17-4);
- }
-
- if(hdr[3]==0x66){
- // NSVf
- int len=stream_read_dword_le(demuxer->stream);
- // TODO: parse out metadata!!!!
- stream_skip(demuxer->stream,len-8);
-
- // NSVs
- stream_read(demuxer->stream,hdr,17);
- if (stream_eof(demuxer->stream) || strncmp(hdr, "NSVs", 4))
- return 0;
- }
-
- // dummy debug message
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_nsv: Header: %.12s\n",hdr);
-
- // bytes 8-11 audio codec fourcc
- // PCM fourcc needs extra parsing for every audio chunk, yet to implement
- if((demuxer->audio->id != -2) && strncmp(hdr+8,"NONE", 4)){//&&strncmp(hdr+8,"VLB ", 4)){
- sh_audio = new_sh_audio ( demuxer, 0 );
- demuxer->audio->id = 0;
- demuxer->audio->sh = sh_audio;
- sh_audio->format=mmioFOURCC(hdr[8],hdr[9],hdr[10],hdr[11]);
- sh_audio->ds = demuxer->audio;
- priv->a_format=mmioFOURCC(hdr[8],hdr[9],hdr[10],hdr[11]);
- }
-
- // store hdr fps
- priv->fps=hdr[16];
-
- if ((demuxer->video->id != -2) && strncmp(hdr+4,"NONE", 4)) {
- /* Create a new video stream header */
- sh_video = new_sh_video ( demuxer, 0 );
-
- /* Make sure the demuxer knows about the new video stream header
- * (even though new_sh_video() ought to take care of it)
- */
- demuxer->video->sh = sh_video;
-
- /* Make sure that the video demuxer stream header knows about its
- * parent video demuxer stream (this is getting wacky), or else
- * video_read_properties() will choke
- */
- sh_video->ds = demuxer->video;
-
- // bytes 4-7 video codec fourcc
- priv->v_format = sh_video->format=mmioFOURCC(hdr[4],hdr[5],hdr[6],hdr[7]);
-
- // new video stream! parse header
- sh_video->disp_w=hdr[12]|(hdr[13]<<8);
- sh_video->disp_h=hdr[14]|(hdr[15]<<8);
- sh_video->bih=calloc(1,sizeof(*sh_video->bih));
- sh_video->bih->biSize=sizeof(*sh_video->bih);
- sh_video->bih->biPlanes=1;
- sh_video->bih->biBitCount=24;
- sh_video->bih->biWidth=hdr[12]|(hdr[13]<<8);
- sh_video->bih->biHeight=hdr[14]|(hdr[15]<<8);
- memcpy(&sh_video->bih->biCompression,hdr+4,4);
- sh_video->bih->biSizeImage=sh_video->bih->biWidth*sh_video->bih->biHeight*3;
-
- // here we search for the correct keyframe
- // vp6 keyframe is when the 2nd byte of the vp6 header is
- // 0x36 for VP61 and 0x46 for VP62
- if((priv->v_format==mmioFOURCC('V','P','6','1')) ||
- (priv->v_format==mmioFOURCC('V','P','6','2')) ||
- (priv->v_format==mmioFOURCC('V','P','3','1'))) {
- stream_read(demuxer->stream,buf,10);
- if (((((priv->v_format>>16) & 0xff) == '6') && ((buf[8]&0x0e)!=0x06)) ||
- ((((priv->v_format>>16) & 0xff) == '3') && (buf[8]!=0x00 || buf[9]!=0x08))) {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_nsv: searching %.4s keyframe...\n", (char*)&priv->v_format);
- while(((((priv->v_format>>16) & 0xff) == '6') && ((buf[8]&0x0e)!=0x06)) ||
- ((((priv->v_format>>16) & 0xff) == '3') && (buf[8]!=0x00 || buf[9]!=0x08))){
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_nsv: %.4s block skip.\n", (char*)&priv->v_format);
- videolen=(buf[2]>>4)|(buf[3]<<4)|(buf[4]<<0xC);
- audiolen=(buf[5])|(buf[6]<<8);
- stream_skip(demuxer->stream, videolen+audiolen-3);
- stream_read(demuxer->stream,buf,10);
- if(stream_eof(demuxer->stream)) return 0;
- if(buf[0]==0x4E){
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_nsv: Got NSVs block.\n");
- stream_skip(demuxer->stream,7);
- stream_read(demuxer->stream,buf,10);
- }
- }
- }
-
- // data starts 10 bytes before current pos but later
- // we seek 17 backwards
- stream_skip(demuxer->stream,7);
- }
-
- switch(priv->fps){
- case 0x80:
- sh_video->fps=30;
- break;
- case 0x81:
- sh_video->fps=(float)30000.0/1001.0;
- break;
- case 0x82:
- sh_video->fps=25;
- break;
- case 0x83:
- sh_video->fps=(float)24000.0/1001.0;
- break;
- case 0x85:
- sh_video->fps=(float)15000.0/1001.0;
- break;
- case 0x89:
- sh_video->fps=(float)10000.0/1001.0;
- break;
- default:
- sh_video->fps = (float)priv->fps;
- }
- sh_video->frametime = (float)1.0 / (float)sh_video->fps;
- }
- }
-
- // seek to start of NSV header
- stream_seek(demuxer->stream,stream_tell(demuxer->stream)-17);
-
- return demuxer;
-}
-
-static int nsv_check_file ( demuxer_t* demuxer )
-{
- uint32_t hdr = 0;
- int i;
-
- mp_msg ( MSGT_DEMUX, MSGL_V, "Checking for Nullsoft Streaming Video\n" );
-
- for (i = 0; i < HEADER_SEARCH_SIZE; i++) {
- uint8_t c = stream_read_char(demuxer->stream);
- if (stream_eof(demuxer->stream))
- return 0;
- if (hdr == mmioFOURCC('s', 'V', 'S', 'N') ||
- (hdr == mmioFOURCC('f', 'V', 'S', 'N') && !c)) {
- stream_seek(demuxer->stream,stream_tell(demuxer->stream)-5);
- return DEMUXER_TYPE_NSV;
- }
- hdr = (hdr << 8) | c;
- }
-
- return 0;
-}
-
-static void demux_close_nsv(demuxer_t* demuxer) {
- nsv_priv_t* priv = demuxer->priv;
-
- free(priv);
-
-}
-
-
-const demuxer_desc_t demuxer_desc_nsv = {
- "NullsoftVideo demuxer",
- "nsv",
- "Nullsoft Streaming Video",
- "Reza Jelveh",
- "nsv and nsa streaming files",
- DEMUXER_TYPE_NSV,
- 0, // safe but expensive autodetect
- nsv_check_file,
- demux_nsv_fill_buffer,
- demux_open_nsv,
- demux_close_nsv,
- demux_seek_nsv,
- NULL
-};
diff --git a/libmpdemux/demux_nut.c b/libmpdemux/demux_nut.c
deleted file mode 100644
index e6602ef506..0000000000
--- a/libmpdemux/demux_nut.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-#include <libnut.h>
-
-typedef struct {
- int last_pts; // FIXME
- nut_context_tt * nut;
- nut_stream_header_tt * s;
-} nut_priv_tt;
-
-static size_t mp_read(void * h, size_t len, uint8_t * buf) {
- stream_t * stream = (stream_t*)h;
-
- if(stream_eof(stream)) return 0;
- //len = MIN(len, 5);
-
- return stream_read(stream, buf, len);
-}
-
-static int mp_eof(void * h) {
- stream_t * stream = (stream_t*)h;
- if(stream_eof(stream)) return 1;
- return 0;
-}
-
-static off_t mp_seek(void * h, long long pos, int whence) {
- stream_t * stream = (stream_t*)h;
-
- if (stream->end_pos < stream_tell(stream))
- stream->end_pos = stream_tell(stream);
-
- if (whence == SEEK_CUR) pos += stream_tell(stream);
- else if (whence == SEEK_END) pos += stream->end_pos;
- else if (whence != SEEK_SET) return -1;
-
- if (pos < stream->end_pos && stream->eof) stream_reset(stream);
- if (stream_seek(stream, pos) == 0) return -1;
-
- return pos;
-}
-
-#define ID_STRING "nut/multimedia container"
-#define ID_LENGTH (strlen(ID_STRING) + 1)
-
-static int nut_check_file(demuxer_t * demuxer) {
- uint8_t buf[ID_LENGTH];
-
- if (stream_read(demuxer->stream, buf, ID_LENGTH) != ID_LENGTH) return 0;
-
- if (memcmp(buf, ID_STRING, ID_LENGTH)) return 0;
-
- stream_seek(demuxer->stream, 0);
- return DEMUXER_TYPE_NUT;
-}
-
-static demuxer_t * demux_open_nut(demuxer_t * demuxer) {
- nut_demuxer_opts_tt dopts = {
- .input = {
- .priv = demuxer->stream,
- .seek = mp_seek,
- .read = mp_read,
- .eof = mp_eof,
- .file_pos = stream_tell(demuxer->stream),
- },
- .alloc = { .malloc = NULL },
- .read_index = index_mode,
- .cache_syncpoints = 1,
- };
- nut_priv_tt * priv = demuxer->priv = calloc(1, sizeof(nut_priv_tt));
- nut_context_tt * nut = priv->nut = nut_demuxer_init(&dopts);
- nut_stream_header_tt * s;
- int ret;
- int i;
-
- while ((ret = nut_read_headers(nut, &s, NULL)) == NUT_ERR_EAGAIN);
- if (ret) {
- mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", nut_error(ret));
- return NULL;
- }
-
- priv->s = s;
-
- for (i = 0; s[i].type != -1 && i < 2; i++) switch(s[i].type) {
- case NUT_AUDIO_CLASS: {
- WAVEFORMATEX *wf =
- calloc(sizeof(*wf) +
- s[i].codec_specific_len, 1);
- sh_audio_t* sh_audio = new_sh_audio(demuxer, i);
- int j;
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "nut", i);
-
- sh_audio->wf= wf; sh_audio->ds = demuxer->audio;
- sh_audio->audio.dwSampleSize = 0; // FIXME
- sh_audio->audio.dwScale = s[i].time_base.num;
- sh_audio->audio.dwRate = s[i].time_base.den;
- sh_audio->format = 0;
- for (j = 0; j < s[i].fourcc_len && j < 4; j++)
- sh_audio->format |= s[i].fourcc[j]<<(j*8);
- sh_audio->channels = s[i].channel_count;
- sh_audio->samplerate =
- s[i].samplerate_num / s[i].samplerate_denom;
- sh_audio->i_bps = 0; // FIXME
-
- wf->wFormatTag = sh_audio->format;
- wf->nChannels = s[i].channel_count;
- wf->nSamplesPerSec =
- s[i].samplerate_num / s[i].samplerate_denom;
- wf->nAvgBytesPerSec = 0; // FIXME
- wf->nBlockAlign = 0; // FIXME
- wf->wBitsPerSample = 0; // FIXME
- wf->cbSize = s[i].codec_specific_len;
- if (s[i].codec_specific_len)
- memcpy(wf + 1, s[i].codec_specific,
- s[i].codec_specific_len);
-
- demuxer->audio->id = i;
- demuxer->audio->sh= demuxer->a_streams[i];
- break;
- }
- case NUT_VIDEO_CLASS: {
- BITMAPINFOHEADER * bih =
- calloc(sizeof(*bih) +
- s[i].codec_specific_len, 1);
- sh_video_t * sh_video = new_sh_video(demuxer, i);
- int j;
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Video stream found, -vid %d\n", "nut", i);
-
- sh_video->bih = bih;
- sh_video->ds = demuxer->video;
- sh_video->disp_w = s[i].width;
- sh_video->disp_h = s[i].height;
- sh_video->video.dwScale = s[i].time_base.num;
- sh_video->video.dwRate = s[i].time_base.den;
-
- sh_video->fps = sh_video->video.dwRate/
- (float)sh_video->video.dwScale;
- sh_video->frametime = 1./sh_video->fps;
- sh_video->format = 0;
- for (j = 0; j < s[i].fourcc_len && j < 4; j++)
- sh_video->format |= s[i].fourcc[j]<<(j*8);
- if (!s[i].sample_height) sh_video->aspect = 0;
- else sh_video->aspect =
- s[i].sample_width / (float)s[i].sample_height;
- sh_video->i_bps = 0; // FIXME
-
- bih->biSize = sizeof(*bih) +
- s[i].codec_specific_len;
- bih->biWidth = s[i].width;
- bih->biHeight = s[i].height;
- bih->biBitCount = 0; // FIXME
- bih->biSizeImage = 0; // FIXME
- bih->biCompression = sh_video->format;
-
- if (s[i].codec_specific_len)
- memcpy(bih + 1, s[i].codec_specific,
- s[i].codec_specific_len);
-
- demuxer->video->id = i;
- demuxer->video->sh = demuxer->v_streams[i];
- break;
- }
- }
-
- return demuxer;
-}
-
-static int demux_nut_fill_buffer(demuxer_t * demuxer, demux_stream_t * dsds) {
- nut_priv_tt * priv = demuxer->priv;
- nut_context_tt * nut = priv->nut;
- demux_packet_t *dp;
- demux_stream_t *ds;
- nut_packet_tt pd;
- int ret;
- double pts;
-
- demuxer->filepos = stream_tell(demuxer->stream);
- if (stream_eof(demuxer->stream)) return 0;
-
- while ((ret = nut_read_next_packet(nut, &pd)) == NUT_ERR_EAGAIN);
- if (ret) {
- if (ret != NUT_ERR_EOF)
- mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n",
- nut_error(ret));
- return 0; // fatal error
- }
-
- pts = (double)pd.pts * priv->s[pd.stream].time_base.num /
- priv->s[pd.stream].time_base.den;
-
- if (pd.stream == demuxer->audio->id) {
- ds = demuxer->audio;
- }
- else if (pd.stream == demuxer->video->id) {
- ds = demuxer->video;
- }
- else {
- uint8_t buf[pd.len];
- while ((ret = nut_read_frame(nut, &pd.len, buf)) == NUT_ERR_EAGAIN);
- if (ret) {
- mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n",
- nut_error(ret));
- return 0; // fatal error
- }
- return 1;
- }
-
- if (pd.stream == 0) priv->last_pts = pd.pts;
-
- dp = new_demux_packet(pd.len);
-
- dp->pts = pts;
-
- dp->pos = demuxer->filepos;
- dp->keyframe = pd.flags & NUT_FLAG_KEY;
-
- {int len = pd.len;
- while ((ret = nut_read_frame(nut, &len, dp->buffer + pd.len-len)) == NUT_ERR_EAGAIN);
- }
- if (ret) {
- mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n",
- nut_error(ret));
- return 0; // fatal error
- }
-
- ds_add_packet(ds, dp); // append packet to DS stream
- return 1;
-}
-
-static void demux_seek_nut(demuxer_t * demuxer, float time_pos, float audio_delay, int flags) {
- nut_context_tt * nut = ((nut_priv_tt*)demuxer->priv)->nut;
- nut_priv_tt * priv = demuxer->priv;
- int nutflags = 0;
- int ret;
- const int tmp[] = { 0, -1 };
-
- if (!(flags & SEEK_ABSOLUTE)) {
- nutflags |= 1; // relative
- if (time_pos > 0) nutflags |= 2; // forwards
- }
-
- if (flags & SEEK_FACTOR)
- time_pos *= priv->s[0].max_pts *
- (double)priv->s[0].time_base.num /
- priv->s[0].time_base.den;
-
- while ((ret = nut_seek(nut, time_pos, nutflags, tmp)) == NUT_ERR_EAGAIN);
- priv->last_pts = -1;
- if (ret) mp_msg(MSGT_HEADER, MSGL_ERR, "NUT error: %s\n", nut_error(ret));
- demuxer->filepos = stream_tell(demuxer->stream);
-}
-
-static int demux_control_nut(demuxer_t * demuxer, int cmd, void * arg) {
- nut_priv_tt * priv = demuxer->priv;
- switch (cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- *((double *)arg) = priv->s[0].max_pts *
- (double)priv->s[0].time_base.num /
- priv->s[0].time_base.den;
- return DEMUXER_CTRL_OK;
- case DEMUXER_CTRL_GET_PERCENT_POS:
- if (priv->s[0].max_pts == 0 || priv->last_pts == -1)
- return DEMUXER_CTRL_DONTKNOW;
- *((int *)arg) = priv->last_pts * 100 /
- (double)priv->s[0].max_pts;
- return DEMUXER_CTRL_OK;
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-static void demux_close_nut(demuxer_t *demuxer) {
- nut_priv_tt * priv = demuxer->priv;
- if (!priv) return;
- nut_demuxer_uninit(priv->nut);
- free(demuxer->priv);
- demuxer->priv = NULL;
-}
-
-
-const demuxer_desc_t demuxer_desc_nut = {
- "NUT demuxer",
- "nut",
- "libnut",
- "Oded Shimon (ods15)",
- "NUT demuxer, requires libnut",
- DEMUXER_TYPE_NUT,
- 1, // safe check demuxer
- nut_check_file,
- demux_nut_fill_buffer,
- demux_open_nut,
- demux_close_nut,
- demux_seek_nut,
- demux_control_nut
-};
diff --git a/libmpdemux/demux_ogg.c b/libmpdemux/demux_ogg.c
deleted file mode 100644
index 9eea061106..0000000000
--- a/libmpdemux/demux_ogg.c
+++ /dev/null
@@ -1,1660 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <math.h>
-#include <inttypes.h>
-
-#include <libavutil/intreadwrite.h>
-
-#include "options.h"
-#include "mp_msg.h"
-#include "talloc.h"
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-#include "aviprint.h"
-#include "demux_mov.h"
-#include "demux_ogg.h"
-
-#define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
-#define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
-#define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
-
-#ifdef CONFIG_TREMOR
-#include <tremor/ogg.h>
-#include <tremor/ivorbiscodec.h>
-#else
-#include <ogg/ogg.h>
-#include <vorbis/codec.h>
-#endif
-
-#ifdef CONFIG_OGGTHEORA
-#include <theora/theora.h>
-int _ilog (unsigned int); /* defined in many places in theora/lib/ */
-#endif
-
-#define BLOCK_SIZE 4096
-
-/* Theora decoder context : we won't be able to interpret granule positions
- * without using theora_granule_time with the theora_state of the stream.
- * This is duplicated in `vd_theora.c'; put this in a common header?
- */
-#ifdef CONFIG_OGGTHEORA
-typedef struct theora_struct_st {
- theora_state st;
- theora_comment cc;
- theora_info inf;
-} theora_struct_t;
-#endif
-
-//// OggDS headers
-// Header for the new header format
-typedef struct stream_header_video {
- ogg_int32_t width;
- ogg_int32_t height;
-} stream_header_video;
-
-typedef struct stream_header_audio {
- ogg_int16_t channels;
- ogg_int16_t blockalign;
- ogg_int32_t avgbytespersec;
-} stream_header_audio;
-
-typedef struct __attribute__((__packed__)) stream_header {
- char streamtype[8];
- char subtype[4];
-
- ogg_int32_t size; // size of the structure
-
- ogg_int64_t time_unit; // in reference time
- ogg_int64_t samples_per_unit;
- ogg_int32_t default_len; // in media time
-
- ogg_int32_t buffersize;
- ogg_int16_t bits_per_sample;
-
- ogg_int16_t padding;
-
- union {
- // Video specific
- stream_header_video video;
- // Audio specific
- stream_header_audio audio;
- } sh;
-} stream_header;
-
-/// Our private datas
-
-typedef struct ogg_syncpoint {
- int64_t granulepos;
- off_t page_pos;
-} ogg_syncpoint_t;
-
-/// A logical stream
-typedef struct ogg_stream {
- /// Timestamping stuff
- float samplerate; /// granulpos 2 time
- int64_t lastpos;
- int32_t lastsize;
- int keyframe_frequency_force;
-
- // Logical stream state
- ogg_stream_state stream;
- int hdr_packets;
- int vorbis;
- int speex;
- int theora;
- int flac;
- int text;
- int id;
-
- vorbis_info vi;
- int vi_initialized;
-
- void *ogg_d;
-} ogg_stream_t;
-
-typedef struct ogg_demuxer {
- /// Physical stream state
- ogg_sync_state sync;
- /// Current page
- ogg_page page;
- /// Logical streams
- ogg_stream_t *subs;
- int num_sub;
- ogg_syncpoint_t *syncpoints;
- int num_syncpoint;
- off_t pos, last_size;
- int64_t initial_granulepos;
- int64_t final_granulepos;
- int64_t duration;
-
- /* Used for subtitle switching. */
- int n_text;
- int *text_ids;
- char **text_langs;
-} ogg_demuxer_t;
-
-#define NUM_VORBIS_HDR_PACKETS 3
-
-/// Some defines from OggDS
-#define PACKET_TYPE_HEADER 0x01
-#define PACKET_TYPE_BITS 0x07
-#define PACKET_LEN_BITS01 0xc0
-#define PACKET_LEN_BITS2 0x02
-#define PACKET_IS_SYNCPOINT 0x08
-
-//-------- subtitle support - should be moved to decoder layer, and queue
-// - subtitles up in demuxer buffer...
-
-#include "sub/subreader.h"
-#include "sub/sub.h"
-#define OGG_SUB_MAX_LINE 128
-
-static subtitle ogg_sub;
-//FILE* subout;
-
-static void demux_ogg_add_sub(ogg_stream_t *os, ogg_packet *pack)
-{
- int lcv;
- char *packet = pack->packet;
-
- if (pack->bytes < 4)
- return;
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
- (unsigned char)packet[0],
- (unsigned char)packet[1],
- (unsigned char)packet[2],
- &packet[3]);
-
- if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
- // Find data start
- double endpts = MP_NOPTS_VALUE;
- int32_t duration = 0;
- int16_t hdrlen = (*packet & PACKET_LEN_BITS01) >> 6, i;
-
- hdrlen |= (*packet & PACKET_LEN_BITS2) << 1;
- lcv = 1 + hdrlen;
- if (pack->bytes < lcv)
- return;
- for (i = hdrlen; i > 0; i--) {
- duration <<= 8;
- duration |= (unsigned char)packet[i];
- }
- if (hdrlen > 0 && duration > 0) {
- float pts;
-
- if (pack->granulepos == -1)
- pack->granulepos = os->lastpos + os->lastsize;
- pts = (float)pack->granulepos / (float)os->samplerate;
- endpts = 1.0 + pts + (float)duration / 1000.0;
- }
- sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
- sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
- }
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg sub lines: %d first: '%s'\n",
- ogg_sub.lines, ogg_sub.text[0]);
-#ifdef CONFIG_ICONV
- subcp_recode(&ogg_sub);
-#endif
- vo_sub = &ogg_sub;
- vo_osd_changed(OSDTYPE_SUBTITLE);
-}
-
-
-// get the logical stream of the current page
-// fill os if non NULL and return the stream id
-static int demux_ogg_get_page_stream(ogg_demuxer_t *ogg_d,
- ogg_stream_state **os)
-{
- int id, s_no;
- ogg_page *page = &ogg_d->page;
-
- s_no = ogg_page_serialno(page);
-
- for (id = 0; id < ogg_d->num_sub; id++)
- if (s_no == ogg_d->subs[id].stream.serialno)
- break;
-
- if (id == ogg_d->num_sub) {
- // If we have only one vorbis stream allow the stream id to change
- // it's normal on radio stream (each song have an different id).
- // But we (or the codec?) should check that the samplerate, etc
- // doesn't change (for radio stream it's ok)
- if (ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
- ogg_stream_reset(&ogg_d->subs[0].stream);
- ogg_stream_init(&ogg_d->subs[0].stream, s_no);
- id = 0;
- } else
- return -1;
- }
-
- if (os)
- *os = &ogg_d->subs[id].stream;
-
- return id;
-}
-
-static unsigned char *demux_ogg_read_packet(ogg_stream_t *os, ogg_packet *pack,
- float *pts, bool *keyframe,
- int samplesize)
-{
- unsigned char *data = pack->packet;
-
- *pts = MP_NOPTS_VALUE;
- *keyframe = false;
-
- if (os->vorbis) {
- if (*pack->packet & PACKET_TYPE_HEADER) {
- os->hdr_packets++;
- } else {
- vorbis_info *vi;
- int32_t blocksize = 0;
-
- // When we dump the audio, there is no vi, but we don't care of timestamp in this case
- vi = os->vi_initialized ? &os->vi : NULL;
- if (vi)
- blocksize = vorbis_packet_blocksize(vi, pack) / samplesize;
- // Calculate the timestamp if the packet don't have any
- if (pack->granulepos == -1) {
- pack->granulepos = os->lastpos;
- if (os->lastsize > 0)
- pack->granulepos += os->lastsize;
- } else
- *keyframe = true;
- if (vi)
- *pts = pack->granulepos / (float)vi->rate;
- os->lastsize = blocksize;
- os->lastpos = pack->granulepos;
- }
- } else if (os->speex) {
- // whole packet (default)
-# ifdef CONFIG_OGGTHEORA
- } else if (os->theora) {
- /* we pass complete packets to theora, mustn't strip the header! */
- os->lastsize = 1;
-
- /* header packets begin on 1-bit: thus check (*data&0x80). We don't
- have theora_state st, until all header packets were passed to the
- decoder. */
- if (!pack->bytes || !(*data&0x80)) {
- int keyframe_granule_shift = _ilog(os->keyframe_frequency_force - 1);
- int64_t iframemask = (1 << keyframe_granule_shift) - 1;
-
- if (pack->granulepos >= 0) {
- os->lastpos = pack->granulepos >> keyframe_granule_shift;
- os->lastpos += pack->granulepos & iframemask;
- *keyframe = (pack->granulepos & iframemask) == 0;
- } else {
- os->lastpos++;
- }
- pack->granulepos = os->lastpos;
- *pts = (double)os->lastpos / (double)os->samplerate;
- }
-#endif /* CONFIG_OGGTHEORA */
- } else if (os->flac) {
- /* we pass complete packets to flac, mustn't strip the header! */
- if (os->flac == 2 && pack->packet[0] != 0xff)
- return NULL;
- } else {
- if (*pack->packet & PACKET_TYPE_HEADER) {
- os->hdr_packets++;
- } else {
- // Find data start
- int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01) >> 6;
-
- hdrlen |= (*pack->packet & PACKET_LEN_BITS2) << 1;
- data = pack->packet + 1 + hdrlen;
- // Calculate the timestamp
- if (pack->granulepos == -1)
- pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
- // If we already have a timestamp it can be a syncpoint
- if (*pack->packet & PACKET_IS_SYNCPOINT)
- *keyframe = true;
- *pts = pack->granulepos / os->samplerate;
- // Save the packet length and timestamp
- os->lastsize = 0;
- while (hdrlen) {
- os->lastsize <<= 8;
- os->lastsize |= pack->packet[hdrlen];
- hdrlen--;
- }
- os->lastpos = pack->granulepos;
- }
- }
- return data;
-}
-
-// check if clang has substring from comma separated langlist
-static int demux_ogg_check_lang(const char *clang, char **langlist)
-{
- if (!langlist)
- return 0;
- for (int i = 0; langlist[i]; i++)
- if (!strncasecmp(clang, langlist[i], strlen(langlist[i])))
- return 1;
- return 0;
-}
-
-/** \brief Change the current subtitle stream and return its ID.
-
- \param demuxer The demuxer whose subtitle stream will be changed.
- \param new_num The number of the new subtitle track. The number must be
- between 0 and ogg_d->n_text - 1.
-
- \returns The Ogg stream number ( = page serial number) of the newly selected
- track.
- */
-static int demux_ogg_sub_id(demuxer_t *demuxer, int index)
-{
- ogg_demuxer_t *ogg_d = demuxer->priv;
- return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
-}
-
-/** \brief Translate the ogg track number into the subtitle number.
- * \param demuxer The demuxer about whose subtitles we are inquiring.
- * \param id The ogg track number of the subtitle track.
- */
-static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id)
-{
- ogg_demuxer_t *ogg_d = demuxer->priv;
- int i;
-
- for (i = 0; i < ogg_d->n_text; i++)
- if (ogg_d->text_ids[i] == id)
- return i;
- return -1;
-}
-
-/// Try to print out comments and also check for LANGUAGE= tag
-static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os,
- int id, vorbis_comment *vc)
-{
- const char *hdr, *val;
- char **cmt = vc->user_comments;
- int index, i;
- ogg_demuxer_t *ogg_d = d->priv;
- static const struct table {
- const char *ogg;
- const char *mp;
- } table[] = {
- { "ENCODED_USING", "Software" },
- { "ENCODER_URL", "Encoder URL" },
- { "TITLE", "Title" },
- { "ARTIST", "Artist" },
- { "COMMENT", "Comments" },
- { "DATE", "Creation Date" },
- { "GENRE", "Genre" },
- { "ALBUM", "Album" },
- { "TRACKNUMBER", "Track" },
- { NULL, NULL },
- };
-
- while (*cmt) {
- hdr = val = NULL;
- if (!strncasecmp(*cmt, "LANGUAGE=", 9)) {
- val = *cmt + 9;
- if (ogg_d->subs[id].text)
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n",
- ogg_d->subs[id].id, val);
- else if (id != d->video->id)
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n",
- ogg_d->subs[id].id, val);
- if (ogg_d->subs[id].text)
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] Language for -sid %d is '-slang \"%s\"'\n",
- ogg_d->subs[id].id, val);
- // copy this language name into the array
- index = demux_ogg_sub_reverse_id(d, id);
- if (index >= 0) {
- sh_sub_t *sh;
-
- // in case of malicious files with more than one lang per track:
- free(ogg_d->text_langs[index]);
- ogg_d->text_langs[index] = strdup(val);
- sh = d->s_streams[index];
- if (sh) {
- talloc_free(sh->lang);
- sh->lang = talloc_strdup(sh, val);
- }
- }
- // check for -slang if subs are uninitialized yet
- if (os->text && d->sub->id < 0
- && demux_ogg_check_lang(val, d->opts->sub_lang)) {
- d->sub->id = index;
- d->opts->sub_id = index;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n",
- id, val);
- }
- else
- hdr = "Language";
- }
- else {
- for (i = 0; table[i].ogg; i++) {
- if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
- (*cmt)[strlen(table[i].ogg)] == '=') {
- hdr = table[i].mp;
- val = *cmt + strlen(table[i].ogg) + 1;
- }
- }
- }
- if (hdr)
- demux_info_add(d, hdr, val);
- mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
- cmt++;
- }
-}
-
-/// Calculate the timestamp and add the packet to the demux stream
-// return 1 if the packet was added, 0 otherwise
-static int demux_ogg_add_packet(demux_stream_t *ds, ogg_stream_t *os,
- int id, ogg_packet *pack)
-{
- demuxer_t *d = ds->demuxer;
- int samplesize = 1;
-
- // If packet is an comment header then we try to get comments at first
- if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7)) {
- vorbis_info vi;
- vorbis_comment vc;
-
- vorbis_info_init(&vi);
- vorbis_comment_init(&vc);
- vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
- if (vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
- demux_ogg_check_comments(d, os, id, &vc);
- vorbis_comment_clear(&vc);
- vorbis_info_clear(&vi);
- }
- if (os->text) {
- if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
- demux_ogg_add_sub(os, pack);
- return 0;
- }
- if (os->speex) {
- // discard first two packets, they contain the header and comment
- if (os->hdr_packets < 2) {
- os->hdr_packets++;
- return 0;
- }
- } else {
- // If packet is an header we jump it except for vorbis and theora
- // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
- // We jump nothing for FLAC. Ain't this great? Packet contents have to be
- // handled differently for each and every stream type. The joy! The joy!
- if (!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
- (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
- (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
- return 0;
- }
-
- // For vorbis packet the packet is the data, for other codec we must jump
- // the header
- if (ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
- samplesize = ((sh_audio_t *)ds->sh)->samplesize;
- }
- bool keyframe;
- float pts;
- unsigned char *data;
- data = demux_ogg_read_packet(os, pack, &pts, &keyframe, samplesize);
- if (!data)
- return 0;
-
- /// Clear subtitles if necessary (for broken files)
- if (sub_clear_text(&ogg_sub, pts)) {
- vo_sub = &ogg_sub;
- vo_osd_changed(OSDTYPE_SUBTITLE);
- }
- /// Send the packet
- struct demux_packet *dp;
- dp = new_demux_packet(pack->bytes - (data - pack->packet));
- memcpy(dp->buffer, data, pack->bytes - (data - pack->packet));
- dp->pts = pts;
- dp->keyframe = keyframe;
- ds_add_packet(ds, dp);
- mp_msg(MSGT_DEMUX, MSGL_DBG2,
- "New dp: %p ds=%p pts=%5.3f len=%d keyframe=%d \n",
- dp, ds, pts, dp->len, keyframe);
- return 1;
-}
-
-/// if -forceidx build a table of all syncpoints to make seeking easier
-/// otherwise try to get at least the final_granulepos
-static void demux_ogg_scan_stream(demuxer_t *demuxer)
-{
- ogg_demuxer_t *ogg_d = demuxer->priv;
- stream_t *s = demuxer->stream;
- ogg_sync_state *sync = &ogg_d->sync;
- ogg_page *page = &ogg_d->page;
- ogg_stream_state *oss;
- ogg_stream_t *os;
- ogg_packet op;
- int np, sid, p, samplesize = 1;
- off_t pos, last_pos;
-
- pos = last_pos = demuxer->movi_start;
-
- // Reset the stream
- stream_seek(s, demuxer->movi_start);
- ogg_sync_reset(sync);
-
- // Get the serial number of the stream we use
- if (demuxer->video->id >= 0) {
- sid = demuxer->video->id;
- } else if (demuxer->audio->id >= 0) {
- sid = demuxer->audio->id;
- if (((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS)
- samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
- } else
- return;
- os = &ogg_d->subs[sid];
- oss = &os->stream;
-
- while (1) {
- np = ogg_sync_pageseek(sync, page);
- if (np < 0) { // We had to skip some bytes
- if (index_mode == 2)
- mp_msg(MSGT_DEMUX, MSGL_ERR,
- "Bad page sync while building syncpoints table (%d)\n",
- -np);
- pos += -np;
- continue;
- }
- if (np <= 0) { // We need more data
- char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
- int len = stream_read(s, buf, BLOCK_SIZE);
-
- if (len == 0 && s->eof)
- break;
- ogg_sync_wrote(sync, len);
- continue;
- }
- // The page is ready
- //ogg_sync_pageout(sync, page);
- if (ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
- pos += np;
- continue;
- }
- if (ogg_stream_pagein(oss, page) != 0) {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Pagein error ????\n");
- pos += np;
- continue;
- }
- p = 0;
- while (ogg_stream_packetout(oss, &op) == 1) {
- float pts;
- bool keyframe;
-
- demux_ogg_read_packet(os, &op, &pts, &keyframe, samplesize);
- if (op.granulepos >= 0) {
- ogg_d->final_granulepos = op.granulepos;
- if (ogg_d->initial_granulepos == MP_NOPTS_VALUE && keyframe) {
- ogg_d->initial_granulepos = op.granulepos;
- if (index_mode != 2 && ogg_d->pos < demuxer->movi_end - 2 * 270000) {
- //the 270000 are just a wild guess
- stream_seek(s, FFMAX(ogg_d->pos, demuxer->movi_end - 270000));
- ogg_sync_reset(sync);
- continue;
- }
- }
- }
- if (index_mode == 2 && (keyframe || (os->vorbis && op.granulepos >= 0))) {
- if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1)
- break;
- ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints, (ogg_d->num_syncpoint + 1), sizeof(ogg_syncpoint_t));
- ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
- ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
- ogg_d->num_syncpoint++;
- }
- p++;
- }
- if (p > 1 || (p == 1 && !ogg_page_continued(page)))
- last_pos = pos;
- pos += np;
- if (index_mode == 2)
- mp_msg(MSGT_DEMUX, MSGL_INFO, "Building syncpoint table %d%%\r",
- (int)(pos * 100 / s->end_pos));
- }
-
- if (index_mode == 2) {
- mp_msg(MSGT_DEMUX, MSGL_INFO, "\n");
- mp_msg(MSGT_DEMUX, MSGL_V,
- "Ogg syncpoints table builed: %d syncpoints\n",
- ogg_d->num_syncpoint);
- }
-
- mp_msg(MSGT_DEMUX, MSGL_V, "Ogg stream length (granulepos): %"PRId64"\n",
- ogg_d->final_granulepos);
-
- stream_reset(s);
- stream_seek(s, demuxer->movi_start);
- ogg_sync_reset(sync);
- for (np = 0; np < ogg_d->num_sub; np++) {
- ogg_stream_reset(&ogg_d->subs[np].stream);
- ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
- }
-
- // Get the first page
- while (1) {
- np = ogg_sync_pageout(sync, page);
- if (np <= 0) { // We need more data
- char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
- int len = stream_read(s, buf, BLOCK_SIZE);
-
- if (len == 0 && s->eof) {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "EOF while trying to get the first page !!!!\n");
- break;
- }
- ogg_sync_wrote(sync, len);
- continue;
- }
- demux_ogg_get_page_stream(ogg_d, &oss);
- ogg_stream_pagein(oss, page);
- break;
- }
-}
-
-static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
-{
- int i, offset;
- int ris, init_error = 0;
- ogg_packet op[3];
- unsigned char *buf[3];
- unsigned char *ptr;
- unsigned int len;
- ogg_stream_t *os = &od->subs[sh->ds->id];
- vorbis_comment vc;
-
- vorbis_info_init(&os->vi);
- vorbis_comment_init(&vc);
- for (i = 0; i < 3; i++) {
- op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
- mp_msg(MSGT_DEMUX, MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
- if (op[i].bytes < 0) {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
- return;
- }
- buf[i] = malloc(op[i].bytes);
- if (!buf[i])
- return;
- memcpy(buf[i], op[i].packet, op[i].bytes);
-
- op[i].b_o_s = (i == 0);
- ris = vorbis_synthesis_headerin(&os->vi, &vc, &op[i]);
- if (ris < 0) {
- init_error = 1;
- mp_msg(MSGT_DECAUDIO, MSGL_ERR, "DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
- }
- }
- vorbis_comment_clear(&vc);
- if (!init_error)
- os->vi_initialized = 1;
-
- len = op[0].bytes + op[1].bytes + op[2].bytes;
- sh->wf = calloc(1, sizeof(*sh->wf) + len + len / 255 + 64);
- ptr = (unsigned char*)(sh->wf + 1);
-
- ptr[0] = 2;
- offset = 1;
- offset += store_ughvlc(&ptr[offset], op[0].bytes);
- mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 1st len = %u\n", offset);
- offset += store_ughvlc(&ptr[offset], op[1].bytes);
- mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 2nd len = %u\n", offset);
- for (i = 0; i < 3; i++) {
- mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
- memcpy(&ptr[offset], buf[i], op[i].bytes);
- offset += op[i].bytes;
- }
- sh->wf->cbSize = offset;
- mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
- sh->wf = realloc(sh->wf, sizeof(*sh->wf) + sh->wf->cbSize);
-
- if (op[0].bytes >= 29) {
- unsigned int br;
- int nombr, minbr, maxbr;
-
- ptr = buf[0];
- sh->channels = ptr[11];
- sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
- maxbr = AV_RL32(&ptr[16]); //max
- nombr = AV_RL32(&ptr[20]); //nominal
- minbr = AV_RL32(&ptr[24]); //minimum
-
- if (maxbr == -1)
- maxbr = 0;
- if (nombr == -1)
- nombr = 0;
- if (minbr == -1)
- minbr = 0;
-
- br = maxbr / 8;
- if (!br)
- br = nombr / 8;
- if (!br)
- br = minbr / 8;
- sh->wf->nAvgBytesPerSec = br;
- sh->wf->wBitsPerSample = 16;
- sh->samplesize = (sh->wf->wBitsPerSample + 7) / 8;
-
- mp_msg(MSGT_DEMUX, MSGL_V,
- "demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n",
- sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec,
- maxbr, nombr, minbr);
- }
- free(buf[2]);
- free(buf[1]);
- free(buf[0]);
-}
-
-/// Open an ogg physical stream
-// Not static because it's used also in demuxer_avi.c
-int demux_ogg_open(demuxer_t *demuxer)
-{
- ogg_demuxer_t *ogg_d;
- stream_t *s;
- char *buf;
- int np, s_no, n_audio = 0, n_video = 0;
- int audio_id = -1, video_id = -1, text_id = -1;
- ogg_sync_state *sync;
- ogg_page *page;
- ogg_packet pack;
- sh_audio_t *sh_a;
- sh_video_t *sh_v;
-
-#ifdef CONFIG_ICONV
- subcp_open(NULL);
-#endif
-
- s = demuxer->stream;
-
- demuxer->priv = ogg_d = calloc(1, sizeof(*ogg_d));
- sync = &ogg_d->sync;
- page = &ogg_d->page;
-
- ogg_sync_init(sync);
-
- while (1) {
- /// Try to get a page
- ogg_d->pos += ogg_d->last_size;
- np = ogg_sync_pageseek(sync, page);
- /// Error
- if (np < 0) {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg demuxer : Bad page sync\n");
- goto err_out;
- }
- /// Need some more data
- if (np == 0) {
- int len;
-
- buf = ogg_sync_buffer(sync, BLOCK_SIZE);
- len = stream_read(s, buf, BLOCK_SIZE);
- if (len == 0 && s->eof) {
- goto err_out;
- }
- ogg_sync_wrote(sync, len);
- continue;
- }
- ogg_d->last_size = np;
- // We got one page now
-
- if (!ogg_page_bos(page)) { // It's not a beginning page
- // Header parsing end here, we need to get the page otherwise it will be lost
- int id = demux_ogg_get_page_stream(ogg_d, NULL);
- if (id >= 0)
- ogg_stream_pagein(&ogg_d->subs[id].stream, page);
- else
- mp_msg(MSGT_DEMUX, MSGL_ERR,
- "Ogg : Warning found none bos page from unknown stream %d\n",
- ogg_page_serialno(page));
- break;
- }
-
- /// Init the data structure needed for a logical stream
- ogg_d->subs = realloc_struct(ogg_d->subs, ogg_d->num_sub+1,
- sizeof(ogg_stream_t));
- memset(&ogg_d->subs[ogg_d->num_sub], 0, sizeof(ogg_stream_t));
- /// Get the stream serial number
- s_no = ogg_page_serialno(page);
- ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream, s_no);
- mp_msg(MSGT_DEMUX, MSGL_DBG2,
- "Ogg : Found a stream with serial=%d\n", s_no);
- // Take the first page
- ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream, page);
- // Get first packet of the page
- ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack);
-
- // Reset our vars
- sh_a = NULL;
- sh_v = NULL;
-
- ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
-
- // Check for Vorbis
- if (pack.bytes >= 7 && !strncmp(&pack.packet[1], "vorbis", 6)) {
- sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
- sh_a->format = FOURCC_VORBIS;
- ogg_d->subs[ogg_d->num_sub].vorbis = 1;
- ogg_d->subs[ogg_d->num_sub].id = n_audio;
- n_audio++;
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: audio (Vorbis), -aid %d\n",
- ogg_d->num_sub, n_audio - 1);
- } else if (pack.bytes >= 80 && !strncmp(pack.packet, "Speex", 5)) {
- sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
- sh_a->wf = calloc(1, sizeof(*sh_a->wf) + pack.bytes);
- sh_a->format = FOURCC_SPEEX;
- sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
- sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
- sh_a->wf->wFormatTag = sh_a->format;
- sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
- sh_a->wf->nBlockAlign = 0;
- sh_a->wf->wBitsPerSample = 16;
- sh_a->samplesize = 2;
- sh_a->wf->cbSize = pack.bytes;
- memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
-
- ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
- ogg_d->subs[ogg_d->num_sub].speex = 1;
- ogg_d->subs[ogg_d->num_sub].id = n_audio;
- n_audio++;
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: audio (Speex), -aid %d\n",
- ogg_d->num_sub, n_audio - 1);
-
- // check for Theora
-#ifdef CONFIG_OGGTHEORA
- } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
- int errorCode = 0;
- theora_info inf;
- theora_comment cc;
-
- theora_info_init (&inf);
- theora_comment_init (&cc);
-
- errorCode = theora_decode_header (&inf, &cc, &pack);
- if (errorCode) {
- mp_msg(MSGT_DEMUX, MSGL_ERR,
- "Theora header parsing failed: %i \n", errorCode);
- } else {
- sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
-
- sh_v->bih = calloc(1, sizeof(*sh_v->bih));
- sh_v->bih->biSize = sizeof(*sh_v->bih);
- sh_v->bih->biCompression = sh_v->format = FOURCC_THEORA;
- sh_v->fps = ((double)inf.fps_numerator) / (double)inf.fps_denominator;
- sh_v->frametime = ((double)inf.fps_denominator) / (double)inf.fps_numerator;
- sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
- sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
- sh_v->bih->biBitCount = 24;
- sh_v->bih->biPlanes = 3;
- sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount / 8) * sh_v->bih->biWidth * sh_v->bih->biHeight);
- ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
- ogg_d->subs[ogg_d->num_sub].theora = 1;
- ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
- ogg_d->subs[ogg_d->num_sub].id = n_video;
- n_video++;
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
- ogg_d->num_sub,
- (int)inf.version_major,
- (int)inf.version_minor,
- (int)inf.version_subminor,
- n_video - 1);
- if (mp_msg_test(MSGT_HEADER, MSGL_V))
- print_video_header(sh_v->bih, MSGL_V);
- }
- theora_comment_clear(&cc);
- theora_info_clear(&inf);
-#endif /* CONFIG_OGGTHEORA */
- } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
- sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
- sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
- ogg_d->subs[ogg_d->num_sub].id = n_audio;
- n_audio++;
- ogg_d->subs[ogg_d->num_sub].flac = 1;
- sh_a->wf = NULL;
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: audio (FLAC), -aid %d\n",
- ogg_d->num_sub, n_audio - 1);
- } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
- sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
- sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
- ogg_d->subs[ogg_d->num_sub].id = n_audio;
- n_audio++;
- ogg_d->subs[ogg_d->num_sub].flac = 2;
- sh_a->wf = calloc(1, sizeof(*sh_a->wf) + 34);
- sh_a->wf->wFormatTag = sh_a->format;
- sh_a->wf->cbSize = 34;
- memcpy(&sh_a->wf[1], &pack.packet[17], 34);
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",
- ogg_d->num_sub, n_audio - 1);
-
- /// Check for old header
- } else if (pack.bytes >= 142 &&
- !strncmp(&pack.packet[1], "Direct Show Samples embedded in Ogg", 35)) {
-
- // Old video header
- if (AV_RL32(pack.packet + 96) == 0x05589f80 && pack.bytes >= 184) {
- sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
- sh_v->bih = calloc(1, sizeof(*sh_v->bih));
- sh_v->bih->biSize = sizeof(*sh_v->bih);
- sh_v->bih->biCompression = sh_v->format = mmioFOURCC(pack.packet[68], pack.packet[69],
- pack.packet[70], pack.packet[71]);
- sh_v->frametime = AV_RL64(pack.packet + 164) * 0.0000001;
- sh_v->fps = 1 / sh_v->frametime;
- sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet + 176);
- sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet + 180);
- sh_v->bih->biBitCount = AV_RL16(pack.packet + 182);
- if (!sh_v->bih->biBitCount)
- sh_v->bih->biBitCount = 24; // hack, FIXME
- sh_v->bih->biPlanes = 1;
- sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
-
- ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
- ogg_d->subs[ogg_d->num_sub].id = n_video;
- n_video++;
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
- ogg_d->num_sub, pack.packet[68], pack.packet[69],
- pack.packet[70], pack.packet[71], n_video - 1);
- if (mp_msg_test(MSGT_HEADER, MSGL_V))
- print_video_header(sh_v->bih, MSGL_V);
- // Old audio header
- } else if (AV_RL32(pack.packet + 96) == 0x05589F81) {
- unsigned int extra_size;
-
- sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
- extra_size = AV_RL16(pack.packet + 140);
- sh_a->wf = calloc(1, sizeof(*sh_a->wf) + extra_size);
- sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet + 124);
- sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet + 126);
- sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet + 128);
- sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet + 132);
- sh_a->wf->nBlockAlign = AV_RL16(pack.packet + 136);
- sh_a->wf->wBitsPerSample = AV_RL16(pack.packet + 138);
- sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
- sh_a->wf->cbSize = extra_size;
- if (extra_size > 0)
- memcpy(sh_a->wf + 1,
- pack.packet + 142, extra_size);
-
- ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
- ogg_d->subs[ogg_d->num_sub].id = n_audio;
- n_audio++;
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
- ogg_d->num_sub, sh_a->format, n_audio - 1);
- if (mp_msg_test(MSGT_HEADER, MSGL_V))
- print_wave_header(sh_a->wf, MSGL_V);
- } else
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- "Ogg stream %d contains an old header but the header type is unknown\n",
- ogg_d->num_sub);
-
- // Check new header
- } else if ((*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
- pack.bytes >= (int)sizeof(stream_header) + 1) {
- stream_header *st = (stream_header*)(pack.packet + 1);
- /// New video header
- if (strncmp(st->streamtype, "video", 5) == 0) {
- sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
- sh_v->bih = calloc(1, sizeof(*sh_v->bih));
- sh_v->bih->biSize = sizeof(*sh_v->bih);
- sh_v->bih->biCompression = sh_v->format = mmioFOURCC(st->subtype[0], st->subtype[1],
- st->subtype[2], st->subtype[3]);
- sh_v->frametime = AV_RL64(&st->time_unit) * 0.0000001;
- sh_v->fps = 1.0 / sh_v->frametime;
- sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
- sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
- sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
- if (!sh_v->bih->biBitCount)
- sh_v->bih->biBitCount = 24; // hack, FIXME
- sh_v->bih->biPlanes = 1;
- sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
-
- ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
- ogg_d->subs[ogg_d->num_sub].id = n_video;
- n_video++;
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
- ogg_d->num_sub, st->subtype[0], st->subtype[1],
- st->subtype[2], st->subtype[3], n_video - 1);
- if (mp_msg_test(MSGT_HEADER, MSGL_V))
- print_video_header(sh_v->bih, MSGL_V);
- /// New audio header
- } else if (strncmp(st->streamtype, "audio", 5) == 0) {
- char buffer[5];
- unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
- unsigned int extra_offset = 0;
-
- memcpy(buffer, st->subtype, 4);
- buffer[4] = '\0';
-
- /* Nasty workaround. stream_header.size seems not to contain the real
- size in all cases. There are four extra bytes that are unaccounted
- for in front of the real codec initialization data _at least_ for
- AAC. So far I've only seen those bytes being all 0, so we can
- just skip them here. */
- if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
- extra_size -= 4;
- extra_offset = 4;
- }
-
- sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
- sh_a->wf = calloc(1, sizeof(*sh_a->wf) + extra_size);
- sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
- sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
- sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
- sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
- sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
- sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
- sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
- sh_a->wf->cbSize = extra_size;
- if (extra_size)
- memcpy(sh_a->wf+1,
- ((char *)(st+1))+extra_offset, extra_size);
-
- ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
- ogg_d->subs[ogg_d->num_sub].id = n_audio;
- n_audio++;
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
- ogg_d->num_sub, sh_a->format, n_audio - 1);
- if (mp_msg_test(MSGT_HEADER, MSGL_V))
- print_wave_header(sh_a->wf, MSGL_V);
-
- /// Check for text (subtitles) header
- } else if (strncmp(st->streamtype, "text", 4) == 0) {
- mp_msg(MSGT_DEMUX, MSGL_INFO,
- "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n",
- ogg_d->num_sub, ogg_d->n_text);
- ogg_d->subs[ogg_d->num_sub].samplerate = AV_RL64(&st->time_unit) / 10;
- ogg_d->subs[ogg_d->num_sub].text = 1;
- ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
- if (demuxer->sub->id == ogg_d->n_text)
- text_id = ogg_d->num_sub;
- new_sh_sub(demuxer, ogg_d->n_text);
- ogg_d->n_text++;
- ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(*ogg_d->text_ids));
- ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
- ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(*ogg_d->text_langs));
- ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
- //// Unknown header type
- } else
- mp_msg(MSGT_DEMUX, MSGL_ERR,
- "Ogg stream %d has a header marker but is of an unknown type\n",
- ogg_d->num_sub);
- /// Unknown (invalid ?) header
- } else
- mp_msg(MSGT_DEMUX, MSGL_ERR,
- "Ogg stream %d is of an unknown type\n",
- ogg_d->num_sub);
-
- if (sh_a || sh_v) {
- demux_stream_t *ds = NULL;
- if (sh_a) {
- // If the audio stream is not defined we took the first one
- if (demuxer->audio->id == -1) {
- demuxer->audio->id = n_audio - 1;
- //if (sh_a->wf) print_wave_header(sh_a->wf, MSGL_INFO);
- }
- /// Is it the stream we want
- if (demuxer->audio->id == n_audio - 1) {
- demuxer->audio->sh = sh_a;
- sh_a->ds = demuxer->audio;
- ds = demuxer->audio;
- audio_id = ogg_d->num_sub;
- }
- }
- if (sh_v) {
- /// Also for video
- if (demuxer->video->id == -1) {
- demuxer->video->id = n_video - 1;
- //if (sh_v->bih) print_video_header(sh_v->bih, MSGL_INFO);
- }
- if (demuxer->video->id == n_video - 1) {
- demuxer->video->sh = sh_v;
- sh_v->ds = demuxer->video;
- ds = demuxer->video;
- video_id = ogg_d->num_sub;
- }
- }
- /// Add the header packets if the stream isn't seekable
- if (ds && !s->end_pos) {
- /// Finish the page, otherwise packets will be lost
- do {
- demux_ogg_add_packet(ds, &ogg_d->subs[ogg_d->num_sub],
- ogg_d->num_sub, &pack);
- } while (ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack) == 1);
- }
- }
- ogg_d->num_sub++;
- }
-
- if (!n_video && !n_audio) {
- goto err_out;
- }
-
- if (!n_video || video_id < 0)
- demuxer->video->id = -2;
- else
- demuxer->video->id = video_id;
- if (!n_audio || audio_id < 0)
- demuxer->audio->id = -2;
- else
- demuxer->audio->id = audio_id;
- /* Disable the subs only if there are no text streams at all.
- Otherwise the stream to display might be chosen later when the comment
- packet is encountered and the user used -slang instead of -sid. */
- if (!ogg_d->n_text)
- demuxer->sub->id = -2;
- else if (text_id >= 0) {
- demuxer->sub->id = text_id;
- mp_msg(MSGT_DEMUX, MSGL_V,
- "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
- }
-
- ogg_d->final_granulepos = 0;
- ogg_d->initial_granulepos = MP_NOPTS_VALUE;
- if (!s->end_pos) {
- demuxer->seekable = 0;
- } else {
- demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
- demuxer->movi_end = s->end_pos;
- demuxer->seekable = 1;
- demux_ogg_scan_stream(demuxer);
- }
- if (ogg_d->initial_granulepos == MP_NOPTS_VALUE)
- ogg_d->initial_granulepos = 0;
- ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos;
-
- mp_msg(MSGT_DEMUX, MSGL_V,
- "Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",
- n_audio, n_audio > 1 ? "s" : "",
- n_video, n_video > 1 ? "s" : "",
- ogg_d->n_text, ogg_d->n_text > 1 ? "s" : "");
-
- sh_a = demuxer->audio->sh;
- if (sh_a && sh_a->format == FOURCC_VORBIS)
- fixup_vorbis_wf(sh_a, ogg_d);
-
- return DEMUXER_TYPE_OGG;
-
-err_out:
- return 0;
-}
-
-static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds)
-{
- ogg_demuxer_t *ogg_d;
- stream_t *s;
- demux_stream_t *ds;
- ogg_sync_state *sync;
- ogg_stream_state *os;
- ogg_page *page;
- ogg_packet pack;
- int np = 0, id=0;
-
- s = d->stream;
- ogg_d = d->priv;
- sync = &ogg_d->sync;
- page = &ogg_d->page;
-
- /// Find the stream we are working on
- if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer : can't get current stream\n");
- return 0;
- }
-
- while (1) {
- np = 0;
- ds = NULL;
- /// Try to get some packet from the current page
- while ((np = ogg_stream_packetout(os, &pack)) != 1) {
- /// No packet we go the next page
- if (np == 0) {
- while (1) {
- int pa, len;
- char *buf;
-
- ogg_d->pos += ogg_d->last_size;
- /// Get the next page from the physical stream
- while ((pa = ogg_sync_pageseek(sync, page)) <= 0) {
- /// Error : we skip some bytes
- if (pa < 0) {
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- "Ogg : Page out not synced, we skip some bytes\n");
- ogg_d->pos -= pa;
- continue;
- }
- /// We need more data
- buf = ogg_sync_buffer(sync, BLOCK_SIZE);
- len = stream_read(s, buf, BLOCK_SIZE);
- if (len == 0 && s->eof) {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg : Stream EOF !!!!\n");
- return 0;
- }
- ogg_sync_wrote(sync, len);
- } /// Page loop
- ogg_d->last_size = pa;
- /// Find the page's logical stream
- if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
- mp_msg(MSGT_DEMUX, MSGL_ERR,
- "Ogg demuxer error : we met an unknown stream\n");
- return 0;
- }
- /// Take the page
- if (ogg_stream_pagein(os, page) == 0)
- break;
- /// Page was invalid => retry
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- "Ogg demuxer : got invalid page !!!!!\n");
- ogg_d->pos += ogg_d->last_size;
- }
- } else /// Packet was corrupted
- mp_msg(MSGT_DEMUX, MSGL_WARN,
- "Ogg : bad packet in stream %d\n", id);
- } /// Packet loop
-
- /// Is the actual logical stream in use ?
- if (id == d->audio->id)
- ds = d->audio;
- else if (id == d->video->id)
- ds = d->video;
- else if (ogg_d->subs[id].text)
- ds = d->sub;
-
- if (ds) {
- if (!demux_ogg_add_packet(ds, &ogg_d->subs[id], id, &pack))
- continue; /// Unuseful packet, get another
- d->filepos = ogg_d->pos;
- return 1;
- }
- } /// while (1)
-}
-
-/// For avi with Ogg audio stream we have to create an ogg demuxer for this
-// stream, then we join the avi and ogg demuxer with a demuxers demuxer
-demuxer_t *init_avi_with_ogg(demuxer_t *demuxer)
-{
- struct MPOpts *opts = demuxer->opts;
- demuxer_t *od;
- ogg_demuxer_t *ogg_d;
- stream_t *s;
- uint32_t hdrsizes[3];
- demux_packet_t *dp;
- sh_audio_t *sh_audio = demuxer->audio->sh;
- int np;
- uint8_t *extradata = (uint8_t *)(sh_audio->wf + 1);
- int i;
- unsigned char *p = NULL, *buf;
- int plen;
-
- /// Check that the cbSize is big enough for the following reads
- if (sh_audio->wf->cbSize < 22 + 3 * 4) {
- mp_msg(MSGT_DEMUX, MSGL_ERR,
- "AVI Ogg : Initial audio header is too small !!!!!\n");
- goto fallback;
- }
- /// Get the size of the 3 header packet
- extradata += 22;
- for (i = 0; i < 3; i++) {
- hdrsizes[i] = AV_RL32(extradata);
- extradata += 4;
- }
- // printf("\n!!!!!! hdr sizes: %d %d %d \n", hdrsizes[0], hdrsizes[1], hdrsizes[2]);
-
- /// Check the size
- if (sh_audio->wf->cbSize < 22 + 3 * 4 + hdrsizes[0] + hdrsizes[1] + hdrsizes[2]) {
- mp_msg(MSGT_DEMUX, MSGL_ERR,
- "AVI Ogg : Audio header is too small !!!!!\n");
- goto fallback;
- }
-
- // Build the ogg demuxer private datas
- ogg_d = calloc(1, sizeof(*ogg_d));
- ogg_d->num_sub = 1;
- ogg_d->subs = malloc(sizeof(*ogg_d->subs));
- ogg_d->subs[0].vorbis = 1;
-
- // Init the ogg physical stream
- ogg_sync_init(&ogg_d->sync);
-
- // Get the first page of the stream : we assume there only 1 logical stream
- while ((np = ogg_sync_pageout(&ogg_d->sync, &ogg_d->page)) <= 0 ) {
- if (np < 0) {
- mp_msg(MSGT_DEMUX, MSGL_ERR,
- "AVI Ogg error : Can't init using first stream packets\n");
- free(ogg_d);
- goto fallback;
- }
- // Add some data
- plen = ds_get_packet(demuxer->audio, &p);
- buf = ogg_sync_buffer(&ogg_d->sync, plen);
- memcpy(buf, p, plen);
- ogg_sync_wrote(&ogg_d->sync, plen);
- }
- // Init the logical stream
- mp_msg(MSGT_DEMUX, MSGL_DBG2,
- "AVI Ogg found page with serial %d\n",
- ogg_page_serialno(&ogg_d->page));
- ogg_stream_init(&ogg_d->subs[0].stream, ogg_page_serialno(&ogg_d->page));
- // Write the page
- ogg_stream_pagein(&ogg_d->subs[0].stream, &ogg_d->page);
-
- // Create the ds_stream and the ogg demuxer
- s = new_ds_stream(demuxer->audio);
- od = new_demuxer(opts, s, DEMUXER_TYPE_OGG, 0, -2, -2, NULL);
-
- /// Add the header packets in the ogg demuxer audio stream
- for (i = 0; i < 3; i++) {
- dp = new_demux_packet(hdrsizes[i]);
- memcpy(dp->buffer, extradata, hdrsizes[i]);
- ds_add_packet(od->audio, dp);
- extradata += hdrsizes[i];
- }
-
- // Finish setting up the ogg demuxer
- od->priv = ogg_d;
- sh_audio = new_sh_audio(od, 0);
- od->audio->id = 0;
- od->video->id = -2;
- od->audio->sh = sh_audio;
- sh_audio->ds = od->audio;
- sh_audio->format = FOURCC_VORBIS;
- fixup_vorbis_wf(sh_audio, ogg_d);
-
- /// Return the joined demuxers
- return new_demuxers_demuxer(demuxer, od, demuxer);
-
-fallback:
- demuxer->audio->id = -2;
- return demuxer;
-
-}
-
-static void demux_ogg_seek(demuxer_t *demuxer, float rel_seek_secs,
- float audio_delay, int flags)
-{
- ogg_demuxer_t *ogg_d = demuxer->priv;
- ogg_sync_state *sync = &ogg_d->sync;
- ogg_page* page= &ogg_d->page;
- ogg_stream_state *oss;
- ogg_stream_t *os;
- demux_stream_t *ds;
- ogg_packet op;
- float rate;
- int i, sp, first = 1, precision = 1, do_seek = 1;
- vorbis_info *vi = NULL;
- int64_t gp = 0, old_gp;
- off_t pos, old_pos;
- int np;
- int is_gp_valid;
- float pts;
- bool is_keyframe;
- int samplesize = 1;
- ogg_int64_t granulepos_orig;
-
- if (demuxer->video->id >= 0) {
- ds = demuxer->video;
- rate = ogg_d->subs[ds->id].samplerate;
- } else {
- ds = demuxer->audio;
- os = &ogg_d->subs[ds->id];
- vi = &(os->vi);
- rate = (float)vi->rate;
- samplesize = ((sh_audio_t*)ds->sh)->samplesize;
- }
-
- os = &ogg_d->subs[ds->id];
- oss = &os->stream;
-
- old_gp = os->lastpos;
- old_pos = ogg_d->pos;
-
- //calculate the granulepos to seek to
- gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos;
- if (flags & SEEK_FACTOR) {
- if (ogg_d->duration > 0)
- gp += ogg_d->duration * rel_seek_secs;
- else
- gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
- } else
- gp += rel_seek_secs * rate;
- if (gp < 0)
- gp = 0;
-
- //calculate the filepos to seek to
- if (ogg_d->syncpoints) {
- for (sp = 0; sp < ogg_d->num_syncpoint; sp++)
- if (ogg_d->syncpoints[sp].granulepos >= gp)
- break;
-
- if (sp >= ogg_d->num_syncpoint)
- return;
- if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp - 1].granulepos)
- sp--;
- if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
- if (sp > 0 && gp < os->lastpos)
- sp--;
- if (sp < ogg_d->num_syncpoint - 1 && gp > os->lastpos)
- sp++;
- }
- pos = ogg_d->syncpoints[sp].page_pos;
- precision = 0;
- } else {
- pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
- if (flags & SEEK_FACTOR)
- pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
- else {
- if (ogg_d->duration > 0) {
- pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate);
- } else if (os->lastpos > 0) {
- pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
- }
- }
- if (pos < 0)
- pos = 0;
- if (pos > (demuxer->movi_end - demuxer->movi_start))
- pos = demuxer->movi_end - demuxer->movi_start;
- } // if (ogg_d->syncpoints)
-
- while (1) {
- if (do_seek) {
- stream_seek(demuxer->stream, pos+demuxer->movi_start);
- ogg_sync_reset(sync);
- for (i = 0; i < ogg_d->num_sub; i++) {
- ogg_stream_reset(&ogg_d->subs[i].stream);
- ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
- }
- ogg_d->pos = pos;
- ogg_d->last_size = 0;
- /* we just guess that we reached correct granulepos, in case a
- subsequent search occurs before we read a valid granulepos */
- os->lastpos = gp;
- first = !(ogg_d->syncpoints);
- do_seek=0;
- }
- ogg_d->pos += ogg_d->last_size;
- ogg_d->last_size = 0;
- np = ogg_sync_pageseek(sync, page);
-
- if (np < 0)
- ogg_d->pos -= np;
- if (np <= 0) { // We need more data
- char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
- int len = stream_read(demuxer->stream, buf, BLOCK_SIZE);
-
- if (len == 0 && demuxer->stream->eof) {
- mp_msg(MSGT_DEMUX, MSGL_V, "EOF while trying to seek !!!!\n");
- return;
- }
- ogg_sync_wrote(sync, len);
- continue;
- }
- ogg_d->last_size = np;
- if (ogg_page_serialno(page) != oss->serialno)
- continue;
-
- if (ogg_stream_pagein(oss, page) != 0)
- continue;
-
- while (1) {
- np = ogg_stream_packetout(oss, &op);
- if (np < 0)
- continue;
- else if (np == 0)
- break;
- if (first) { /* Discard the first packet as it's probably broken,
- and we don't have any other means to decide whether it is
- complete or not. */
- first = 0;
- break;
- }
- is_gp_valid = (op.granulepos >= 0);
- granulepos_orig=op.granulepos;
- demux_ogg_read_packet(os, &op, &pts, &is_keyframe, samplesize);
- if (precision && is_gp_valid) {
- precision--;
- if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
- //prepare another seek because we are off by more than 1s
- pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
- if (pos < 0)
- pos = 0;
- if (pos < demuxer->movi_end - demuxer->movi_start) {
- do_seek=1;
- break;
- }
- }
- }
- if (is_gp_valid && pos > 0 && old_gp > gp
- && 2 * (old_gp - op.granulepos) < old_gp - gp) {
- /* prepare another seek because looking for a syncpoint
- destroyed the backward search */
- pos = old_pos - 1.5 * (old_pos - pos);
- if (pos < 0)
- pos = 0;
- if (pos < demuxer->movi_end - demuxer->movi_start) {
- do_seek=1;
- break;
- }
- }
- if (!precision && (is_keyframe || os->vorbis || os->speex)) {
- if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
- vo_sub = &ogg_sub;
- vo_osd_changed(OSDTYPE_SUBTITLE);
- }
- op.granulepos=granulepos_orig;
- demux_ogg_add_packet(ds, os, ds->id, &op);
- return;
- }
- }
- }
-
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Can't find the good packet :(\n");
-}
-
-static void demux_close_ogg(demuxer_t *demuxer)
-{
- ogg_demuxer_t *ogg_d = demuxer->priv;
- ogg_stream_t *os = NULL;
- int i;
-
- if (!ogg_d)
- return;
-
-#ifdef CONFIG_ICONV
- subcp_close();
-#endif
-
- ogg_sync_clear(&ogg_d->sync);
- if (ogg_d->subs) {
- for (i = 0; i < ogg_d->num_sub; i++) {
- os = &ogg_d->subs[i];
- ogg_stream_clear(&os->stream);
- if (os->vi_initialized)
- vorbis_info_clear(&os->vi);
- }
- free(ogg_d->subs);
- }
- free(ogg_d->syncpoints);
- free(ogg_d->text_ids);
- if (ogg_d->text_langs) {
- for (i = 0; i < ogg_d->n_text; i++)
- free(ogg_d->text_langs[i]);
- free(ogg_d->text_langs);
- }
- free(ogg_d);
-}
-
-static int demux_ogg_control(demuxer_t *demuxer, int cmd, void *arg)
-{
- ogg_demuxer_t *ogg_d = demuxer->priv;
- ogg_stream_t *os;
- float rate;
-
- if (demuxer->video->id >= 0) {
- os = &ogg_d->subs[demuxer->video->id];
- rate = os->samplerate;
- } else {
- os = &ogg_d->subs[demuxer->audio->id];
- rate = os->vi.rate;
- }
-
- switch(cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- if (ogg_d->duration <= 0)
- return DEMUXER_CTRL_DONTKNOW;
- *(double *)arg = (double)(ogg_d->duration) / rate;
- return DEMUXER_CTRL_GUESS;
-
- case DEMUXER_CTRL_GET_PERCENT_POS:
- if (ogg_d->duration <= 0)
- return DEMUXER_CTRL_DONTKNOW;
- *(int *)arg = ((os->lastpos - ogg_d->initial_granulepos) * 100) / ogg_d->duration;
- return DEMUXER_CTRL_OK;
-
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-const demuxer_desc_t demuxer_desc_ogg = {
- "Ogg demuxer",
- "ogg",
- "Ogg",
- "?",
- "",
- DEMUXER_TYPE_OGG,
- 1, // safe autodetect
- demux_ogg_open,
- demux_ogg_fill_buffer,
- NULL,
- demux_close_ogg,
- demux_ogg_seek,
- demux_ogg_control
-};
diff --git a/libmpdemux/demux_ogg.h b/libmpdemux/demux_ogg.h
deleted file mode 100644
index 0bdc30b910..0000000000
--- a/libmpdemux/demux_ogg.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_DEMUX_OGG_H
-#define MPLAYER_DEMUX_OGG_H
-
-#include "demuxer.h"
-
-int demux_ogg_open(demuxer_t *demuxer);
-demuxer_t *init_avi_with_ogg(demuxer_t *demuxer);
-
-#endif /* MPLAYER_DEMUX_OGG_H */
diff --git a/libmpdemux/demux_pva.c b/libmpdemux/demux_pva.c
deleted file mode 100644
index 883641fbc8..0000000000
--- a/libmpdemux/demux_pva.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * demuxer for PVA files, such as the ones produced by software to manage
- * DVB boards like the Hauppauge WinTV DVBs
- * copyright (c) 2002 Matteo Giani
- *
- * Uses info from the PVA file specifications found at
- * http://www.technotrend.de/download/av_format_v1.pdf
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/* WARNING: Quite a hack was required in order to get files by MultiDec
- * played back correctly. If it breaks anything else, just comment out
- * the #define below and it will not be compiled in. */
-#define DEMUX_PVA_MULTIDEC_HACK
-#define PVA_NEW_PREBYTES_CODE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-/*
- * #defines below taken from PVA spec (see URL above)
- */
-
-#define PVA_MAX_VIDEO_PACK_LEN 6*1024
-
-#define VIDEOSTREAM 0x01
-#define MAINAUDIOSTREAM 0x02
-
-typedef struct {
- off_t offset;
- long size;
- uint8_t type;
- uint8_t is_packet_start;
- float pts;
-} pva_payload_t;
-
-
-typedef struct {
- float last_audio_pts;
- float last_video_pts;
-#ifdef PVA_NEW_PREBYTES_CODE
- float video_pts_after_prebytes;
- long video_size_after_prebytes;
- uint8_t prebytes_delivered;
-#endif
- uint8_t just_synced;
- uint8_t synced_stream_id;
-} pva_priv_t;
-
-
-
-static int pva_sync(demuxer_t * demuxer)
-{
- uint8_t buffer[5]={0,0,0,0,0};
- int count;
- pva_priv_t * priv = (pva_priv_t *) demuxer->priv;
-
-
- /* This function is used to find the next nearest PVA packet start after a seek, since a PVA file
- * is not indexed.
- * The just_synced field is in the priv structure so that pva_get_payload knows pva_sync
- * has already read (part of) the PVA header. This way we can avoid to seek back and (hopefully)
- * be able to read from pipes and such.
- */
-
-
- for(count=0 ; count<PVA_MAX_VIDEO_PACK_LEN && !demuxer->stream->eof && !priv->just_synced ; count++)
- {
- buffer[0]=buffer[1];
- buffer[1]=buffer[2];
- buffer[2]=buffer[3];
- buffer[3]=buffer[4];
- buffer[4]=stream_read_char(demuxer->stream);
- /*
- * Check for a PVA packet beginning sequence: we check both the "AV" word at the
- * very beginning and the "0x55" reserved byte (which is unused and set to 0x55 by spec)
- */
- if(buffer[0]=='A' && buffer[1] == 'V' && buffer[4] == 0x55) priv->just_synced=1;
- //printf("demux_pva: pva_sync(): current offset= %ld\n",stream_tell(demuxer->stream));
- }
- if(priv->just_synced)
- {
- priv->synced_stream_id=buffer[2];
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-static int pva_check_file(demuxer_t * demuxer)
-{
- uint8_t buffer[5]={0,0,0,0,0};
- mp_msg(MSGT_DEMUX, MSGL_V, "Checking for PVA\n");
- stream_read(demuxer->stream,buffer,5);
- if(buffer[0]=='A' && buffer[1] == 'V' && buffer[4] == 0x55)
- {
- mp_msg(MSGT_DEMUX,MSGL_DBG2, "Success: PVA\n");
- return DEMUXER_TYPE_PVA;
- }
- else
- {
- mp_msg(MSGT_DEMUX,MSGL_DBG2, "Failed: PVA\n");
- return 0;
- }
-}
-
-static demuxer_t * demux_open_pva (demuxer_t * demuxer)
-{
- sh_video_t *sh_video = new_sh_video(demuxer,0);
- sh_audio_t *sh_audio = new_sh_audio(demuxer,0);
-
-
- pva_priv_t * priv;
-
- stream_reset(demuxer->stream);
- stream_seek(demuxer->stream,0);
-
-
-
- priv=malloc(sizeof(pva_priv_t));
-
- if(demuxer->stream->type!=STREAMTYPE_FILE) demuxer->seekable=0;
- else demuxer->seekable=1;
-
- demuxer->priv=priv;
- memset(demuxer->priv,0,sizeof(pva_priv_t));
-
- if(!pva_sync(demuxer))
- {
- mp_msg(MSGT_DEMUX,MSGL_ERR,"Not a PVA file.\n");
- return NULL;
- }
-
- //printf("priv->just_synced %s after initial sync!\n",priv->just_synced?"set":"UNSET");
-
- demuxer->video->sh=sh_video;
-
- //printf("demuxer->stream->end_pos= %d\n",demuxer->stream->end_pos);
-
-
- mp_msg(MSGT_DEMUXER,MSGL_INFO,"Opened PVA demuxer...\n");
-
- /*
- * Audio and Video codecs:
- * the PVA spec only allows MPEG2 video and MPEG layer II audio. No need to check the formats then.
- * Moreover, there would be no way to do that since the PVA stream format has no fields to describe
- * the used codecs.
- */
-
- sh_video->format=0x10000002;
- sh_video->ds=demuxer->video;
-
- /*
- printf("demuxer->video->id==%d\n",demuxer->video->id);
- printf("demuxer->audio->id==%d\n",demuxer->audio->id);
- */
-
- demuxer->audio->id = 0;
- demuxer->audio->sh=sh_audio;
- sh_audio->format=0x50;
- sh_audio->ds=demuxer->audio;
-
- demuxer->movi_start=0;
- demuxer->movi_end=demuxer->stream->end_pos;
-
- priv->last_video_pts=-1;
- priv->last_audio_pts=-1;
-
- return demuxer;
-}
-
-static int pva_get_payload(demuxer_t *d, pva_payload_t *payload)
-{
- uint8_t flags,pes_head_len;
- uint16_t pack_size;
- off_t pva_payload_start;
- unsigned char buffer[256];
-#ifndef PVA_NEW_PREBYTES_CODE
- demux_packet_t * dp; //hack to deliver the preBytes (see PVA doc)
-#endif
- pva_priv_t * priv;
-
-
- if(d==NULL)
- {
- mp_msg(MSGT_DEMUX,MSGL_ERR,"demux_pva: pva_get_payload got passed a NULL pointer!\n");
- return 0;
- }
-
- priv = (pva_priv_t *)d->priv;
- d->filepos=stream_tell(d->stream);
-
-
-
-
- if(d->stream->eof)
- {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: pva_get_payload() detected stream->eof!!!\n");
- return 0;
- }
-
- //printf("priv->just_synced %s\n",priv->just_synced?"SET":"UNSET");
-
-#ifdef PVA_NEW_PREBYTES_CODE
- if(priv->prebytes_delivered)
- /* The previous call to this fn has delivered the preBytes. Then we are already inside
- * the payload. Let's just deliver the video along with its right PTS, the one we stored
- * in the priv structure and was in the PVA header before the PreBytes.
- */
- {
- //printf("prebytes_delivered=1. Resetting.\n");
- payload->size = priv->video_size_after_prebytes;
- payload->pts = priv->video_pts_after_prebytes;
- payload->is_packet_start = 1;
- payload->offset = stream_tell(d->stream);
- payload->type = VIDEOSTREAM;
- priv->prebytes_delivered = 0;
- return 1;
- }
-#endif
- if(!priv->just_synced)
- {
- if(stream_read_word(d->stream) != (('A'<<8)|'V'))
- {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: pva_get_payload() missed a SyncWord at %"PRId64"!! Trying to sync...\n",(int64_t)stream_tell(d->stream));
- if(!pva_sync(d))
- {
- if (!d->stream->eof)
- {
- mp_msg(MSGT_DEMUX,MSGL_ERR,"demux_pva: couldn't sync! (broken file?)");
- }
- return 0;
- }
- }
- }
- if(priv->just_synced)
- {
- payload->type=priv->synced_stream_id;
- priv->just_synced=0;
- }
- else
- {
- payload->type=stream_read_char(d->stream);
- stream_skip(d->stream,2); //counter and reserved
- }
- flags=stream_read_char(d->stream);
- payload->is_packet_start=flags & 0x10;
- pack_size=stream_read_word(d->stream);
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_pva::pva_get_payload(): pack_size=%u field read at offset %"PRIu64"\n",pack_size,(int64_t)stream_tell(d->stream)-2);
- pva_payload_start=stream_tell(d->stream);
-
-
- /*
- * The code in the #ifdef directive below is a hack needed to get badly formatted PVA files
- * such as the ones written by MultiDec played back correctly.
- * Basically, it works like this: if the PVA packet does not signal a PES header, but the
- * payload looks like one, let's assume it IS one. It has worked for me up to now.
- * It can be disabled since it's quite an ugly hack and could potentially break things up
- * if the PVA audio payload happens to start with 0x000001 even without being a non signalled
- * PES header start.
- * Though it's quite unlikely, it potentially could (AFAIK).
- */
-#ifdef DEMUX_PVA_MULTIDEC_HACK
- if(payload->type==MAINAUDIOSTREAM)
- {
- stream_read(d->stream,buffer,3);
- if(buffer[0]==0x00 && buffer[1]==0x00 && buffer[2]==0x01 && !payload->is_packet_start)
- {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: suspecting non signaled audio PES packet start. Maybe file by MultiDec?\n");
- payload->is_packet_start=1;
- }
- stream_seek(d->stream,stream_tell(d->stream)-3);
- }
-#endif
-
-
- if(!payload->is_packet_start)
- {
- payload->offset=stream_tell(d->stream);
- payload->size=pack_size;
- }
- else
- { //here comes the good part...
- switch(payload->type)
- {
- case VIDEOSTREAM:
- payload->pts=(float)(stream_read_dword(d->stream))/90000;
- //printf("Video PTS: %f\n",payload->pts);
- if((flags&0x03)
-#ifdef PVA_NEW_PREBYTES_CODE
- && !priv->prebytes_delivered
-#endif
- )
- {
-#ifndef PVA_NEW_PREBYTES_CODE
- dp=new_demux_packet(flags&0x03);
- stream_read(d->stream,dp->buffer,flags & 0x03); //read PreBytes
- ds_add_packet(d->video,dp);
-#else
- //printf("Delivering prebytes. Setting prebytes_delivered.");
- payload->offset=stream_tell(d->stream);
- payload->size = flags & 0x03;
- priv->video_pts_after_prebytes = payload->pts;
- priv->video_size_after_prebytes = pack_size - 4 - (flags & 0x03);
- payload->pts=priv->last_video_pts;
- payload->is_packet_start=0;
- priv->prebytes_delivered=1;
- return 1;
-#endif
- }
-
-
- //now we are at real beginning of payload.
- payload->offset=stream_tell(d->stream);
- //size is pack_size minus PTS size minus PreBytes size.
- payload->size=pack_size - 4 - (flags & 0x03);
- break;
- case MAINAUDIOSTREAM:
- stream_skip(d->stream,3); //FIXME properly parse PES header.
- //printf("StreamID in audio PES header: 0x%2X\n",stream_read_char(d->stream));
- stream_skip(d->stream,4);
-
- buffer[255]=stream_read_char(d->stream);
- pes_head_len=stream_read_char(d->stream);
- stream_read(d->stream,buffer,pes_head_len);
- if(!(buffer[255]&0x80)) //PES header does not contain PTS.
- {
- mp_msg(MSGT_DEMUX,MSGL_V,"Audio PES packet does not contain PTS. (pes_head_len=%d)\n",pes_head_len);
- payload->pts=priv->last_audio_pts;
- break;
- }
- else //PES header DOES contain PTS
- {
- if((buffer[0] & 0xf0)!=0x20) // PTS badly formatted
- {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: expected audio PTS but badly formatted... (read 0x%02X). Falling back to previous PTS (hack).\n",buffer[0]);
- payload->pts=priv->last_audio_pts;
- // return 0;
- }
- else
- {
- uint64_t temp_pts;
-
- temp_pts=0LL;
- temp_pts|=((uint64_t)(buffer[0] & 0x0e) << 29);
- temp_pts|=buffer[1]<<22;
- temp_pts|=(buffer[2] & 0xfe) << 14;
- temp_pts|=buffer[3]<<7;
- temp_pts|=(buffer[4] & 0xfe) >> 1;
- /*
- * PTS parsing is hopefully finished.
- */
- payload->pts=(float)temp_pts/90000;
- }
- }
- payload->offset=stream_tell(d->stream);
- payload->size=pack_size-stream_tell(d->stream)+pva_payload_start;
- break;
- }
- }
- return 1;
-}
-
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_pva_fill_buffer (demuxer_t * demux, demux_stream_t *ds)
-{
- uint8_t done=0;
- demux_packet_t * dp;
- pva_priv_t * priv=demux->priv;
- pva_payload_t current_payload;
-
- while(!done)
- {
- if(!pva_get_payload(demux,&current_payload)) return 0;
- switch(current_payload.type)
- {
- case VIDEOSTREAM:
- if(demux->video->id==-1) demux->video->id=0;
- if(!current_payload.is_packet_start && priv->last_video_pts==-1)
- {
- /* We should only be here at the beginning of a stream, when we have
- * not yet encountered a valid Video PTS, or after a seek.
- * So, skip these starting packets in order not to deliver the
- * player a bogus PTS.
- */
- done=0;
- }
- else
- {
- /*
- * In every other condition, we are delivering the payload. Set this
- * so that the following code knows whether to skip it or read it.
- */
- done=1;
- }
- if(demux->video->id!=0) done=0;
- if(current_payload.is_packet_start)
- {
- priv->last_video_pts=current_payload.pts;
- //mp_msg(MSGT_DEMUXER,MSGL_DBG2,"demux_pva: Video PTS=%llu , delivered %f\n",current_payload.pts,priv->last_video_pts);
- }
- if(done)
- {
- dp=new_demux_packet(current_payload.size);
- dp->pts=priv->last_video_pts;
- stream_read(demux->stream,dp->buffer,current_payload.size);
- ds_add_packet(demux->video,dp);
- }
- else
- {
- //printf("Skipping %u video bytes\n",current_payload.size);
- stream_skip(demux->stream,current_payload.size);
- }
- break;
- case MAINAUDIOSTREAM:
- if(demux->audio->id==-1) demux->audio->id=0;
- if(!current_payload.is_packet_start && priv->last_audio_pts==-1)
- {
- /* Same as above for invalid video PTS, just for audio. */
- done=0;
- }
- else
- {
- done=1;
- }
- if(current_payload.is_packet_start)
- {
- priv->last_audio_pts=current_payload.pts;
- }
- if(demux->audio->id!=0) done=0;
- if(done)
- {
- dp=new_demux_packet(current_payload.size);
- dp->pts=priv->last_audio_pts;
- if(current_payload.offset != stream_tell(demux->stream))
- stream_seek(demux->stream,current_payload.offset);
- stream_read(demux->stream,dp->buffer,current_payload.size);
- ds_add_packet(demux->audio,dp);
- }
- else
- {
- stream_skip(demux->stream,current_payload.size);
- }
- break;
- }
- }
- return 1;
-}
-
-static void demux_seek_pva(demuxer_t * demuxer,float rel_seek_secs,float audio_delay,int flags)
-{
- int total_bitrate=0;
- off_t dest_offset;
- pva_priv_t * priv=demuxer->priv;
-
- total_bitrate=((sh_audio_t *)demuxer->audio->sh)->i_bps + ((sh_video_t *)demuxer->video->sh)->i_bps;
-
- /*
- * Compute absolute offset inside the stream. Approximate total bitrate with sum of bitrates
- * reported by the audio and video codecs. The seek is not accurate because, just like
- * with MPEG streams, the bitrate is not constant. Moreover, we do not take into account
- * the overhead caused by PVA and PES headers.
- * If the calculated absolute offset is negative, seek to the beginning of the file.
- */
-
- dest_offset=stream_tell(demuxer->stream)+rel_seek_secs*total_bitrate;
- if(dest_offset<0) dest_offset=0;
-
- stream_seek(demuxer->stream,dest_offset);
-
- if(!pva_sync(demuxer))
- {
- mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: Couldn't seek!\n");
- return;
- }
-
- /*
- * Reset the PTS info inside the pva_priv_t structure. This way we don't deliver
- * data with the wrong PTSs (the ones we had before seeking).
- *
- */
-
- priv->last_video_pts=-1;
- priv->last_audio_pts=-1;
-}
-
-
-
-static void demux_close_pva(demuxer_t * demuxer)
-{
- free(demuxer->priv);
- demuxer->priv = NULL;
-}
-
-
-const demuxer_desc_t demuxer_desc_pva = {
- "PVA demuxer",
- "pva",
- "PVA",
- "Matteo Giani",
- "streams from DVB cards",
- DEMUXER_TYPE_PVA,
- 0, // unsafe autodetect
- pva_check_file,
- demux_pva_fill_buffer,
- demux_open_pva,
- demux_close_pva,
- demux_seek_pva,
- NULL
-};
diff --git a/libmpdemux/demux_roq.c b/libmpdemux/demux_roq.c
deleted file mode 100644
index af9e4c5a8e..0000000000
--- a/libmpdemux/demux_roq.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * RoQ file demuxer
- * copyright (c) 2002 Mike Melanson
- * based on Dr. Tim Ferguson's RoQ document found at:
- * http://www.csse.monash.edu.au/~timf/videocodec.html
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-#include "libavutil/attributes.h"
-
-#define RoQ_INFO 0x1001
-#define RoQ_QUAD_CODEBOOK 0x1002
-#define RoQ_QUAD_VQ 0x1011
-#define RoQ_SOUND_MONO 0x1020
-#define RoQ_SOUND_STEREO 0x1021
-
-#define CHUNK_TYPE_AUDIO 0
-#define CHUNK_TYPE_VIDEO 1
-
-typedef struct roq_chunk_t
-{
- int chunk_type;
- off_t chunk_offset;
- int chunk_size;
-
- float video_chunk_number; // in the case of a video chunk
- int running_audio_sample_count; // for an audio chunk
-} roq_chunk_t;
-
-typedef struct roq_data_t
-{
- int total_chunks;
- int current_chunk;
- int total_video_chunks;
- int total_audio_sample_count;
- roq_chunk_t *chunks;
-} roq_data_t;
-
-// Check if a stream qualifies as a RoQ file based on the magic numbers
-// at the start of the file:
-// 84 10 FF FF FF FF xx xx
-static int roq_check_file(demuxer_t *demuxer)
-{
- if ((stream_read_dword(demuxer->stream) == 0x8410FFFF) &&
- ((stream_read_dword(demuxer->stream) & 0xFFFF0000) == 0xFFFF0000))
- return DEMUXER_TYPE_ROQ;
- else
- return 0;
-}
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_roq_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
-{
- sh_video_t *sh_video = demuxer->video->sh;
- roq_data_t *roq_data = (roq_data_t *)demuxer->priv;
- roq_chunk_t roq_chunk;
-
- if (roq_data->current_chunk >= roq_data->total_chunks)
- return 0;
-
- roq_chunk = roq_data->chunks[roq_data->current_chunk];
-
- // make sure we're at the right place in the stream and fetch the chunk
- stream_seek(demuxer->stream, roq_chunk.chunk_offset);
-
- if (roq_chunk.chunk_type == CHUNK_TYPE_AUDIO)
- ds_read_packet(demuxer->audio, demuxer->stream, roq_chunk.chunk_size,
- 0,
- roq_chunk.chunk_offset, 0);
- else
- ds_read_packet(demuxer->video, demuxer->stream, roq_chunk.chunk_size,
- roq_chunk.video_chunk_number / sh_video->fps,
- roq_chunk.chunk_offset, 0);
-
- roq_data->current_chunk++;
- return 1;
-}
-
-static demuxer_t* demux_open_roq(demuxer_t* demuxer)
-{
- sh_video_t *sh_video = NULL;
- sh_audio_t *sh_audio = NULL;
-
- roq_data_t *roq_data = malloc(sizeof(roq_data_t));
- int chunk_id;
- int chunk_size;
- int chunk_arg av_unused;
- int last_chunk_id = 0;
- int largest_audio_chunk = 0;
- int fps;
-
- roq_data->total_chunks = 0;
- roq_data->current_chunk = 0;
- roq_data->total_video_chunks = 0;
- roq_data->chunks = NULL;
-
- // position the stream and start traversing
- stream_seek(demuxer->stream, 6);
- fps = stream_read_word_le(demuxer->stream);
- while (!stream_eof(demuxer->stream))
- {
- chunk_id = stream_read_word_le(demuxer->stream);
- chunk_size = stream_read_dword_le(demuxer->stream);
- chunk_arg = stream_read_word_le(demuxer->stream);
-
- // this is the only useful header info in the file
- if (chunk_id == RoQ_INFO)
- {
- // there should only be one RoQ_INFO chunk per file
- if (sh_video)
- {
- mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Found more than one RoQ_INFO chunk\n");
- stream_skip(demuxer->stream, 8);
- }
- else
- {
- // this is a good opportunity to create a video stream header
- sh_video = new_sh_video(demuxer, 0);
- // make sure the demuxer knows about the new stream header
- demuxer->video->sh = sh_video;
- // make sure that the video demuxer stream header knows about its
- // parent video demuxer stream
- sh_video->ds = demuxer->video;
-
- sh_video->disp_w = stream_read_word_le(demuxer->stream);
- sh_video->disp_h = stream_read_word_le(demuxer->stream);
- stream_skip(demuxer->stream, 4);
-
- // custom fourcc for internal MPlayer use
- sh_video->format = mmioFOURCC('R', 'o', 'Q', 'V');
-
- // constant frame rate
- sh_video->fps = fps;
- sh_video->frametime = 1 / sh_video->fps;
- }
- }
- else if ((chunk_id == RoQ_SOUND_MONO) ||
- (chunk_id == RoQ_SOUND_STEREO))
- {
- // create the audio stream header if it hasn't been created it
- if (sh_audio == NULL)
- {
- // make the header first
- sh_audio = new_sh_audio(demuxer, 0);
- // make sure the demuxer knows about the new stream header
- demuxer->audio->id = 0;
- demuxer->audio->sh = sh_audio;
- // make sure that the audio demuxer stream header knows about its
- // parent audio demuxer stream
- sh_audio->ds = demuxer->audio;
-
- // go through the bother of making a WAVEFORMATEX structure
- sh_audio->wf = malloc(sizeof(*sh_audio->wf));
-
- // custom fourcc for internal MPlayer use
- sh_audio->format = mmioFOURCC('R', 'o', 'Q', 'A');
- if (chunk_id == RoQ_SOUND_STEREO)
- sh_audio->wf->nChannels = 2;
- else
- sh_audio->wf->nChannels = 1;
- // always 22KHz, 16-bit
- sh_audio->wf->nSamplesPerSec = 22050;
- sh_audio->wf->wBitsPerSample = 16;
- }
-
- // index the chunk
- roq_data->chunks = realloc(roq_data->chunks,
- (roq_data->total_chunks + 1) * sizeof (roq_chunk_t));
- roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_AUDIO;
- roq_data->chunks[roq_data->total_chunks].chunk_offset =
- stream_tell(demuxer->stream) - 8;
- roq_data->chunks[roq_data->total_chunks].chunk_size = chunk_size + 8;
- roq_data->chunks[roq_data->total_chunks].running_audio_sample_count =
- roq_data->total_audio_sample_count;
-
- // audio housekeeping
- if (chunk_size > largest_audio_chunk)
- largest_audio_chunk = chunk_size;
- roq_data->total_audio_sample_count +=
- (chunk_size / sh_audio->wf->nChannels);
-
- stream_skip(demuxer->stream, chunk_size);
- roq_data->total_chunks++;
- }
- else if ((chunk_id == RoQ_QUAD_CODEBOOK) ||
- ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id != RoQ_QUAD_CODEBOOK)))
- {
- // index a new chunk if it's a codebook or quad VQ not following a
- // codebook
- roq_data->chunks = realloc(roq_data->chunks,
- (roq_data->total_chunks + 1) * sizeof (roq_chunk_t));
- roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_VIDEO;
- roq_data->chunks[roq_data->total_chunks].chunk_offset =
- stream_tell(demuxer->stream) - 8;
- roq_data->chunks[roq_data->total_chunks].chunk_size = chunk_size + 8;
- roq_data->chunks[roq_data->total_chunks].video_chunk_number =
- roq_data->total_video_chunks++;
-
- stream_skip(demuxer->stream, chunk_size);
- roq_data->total_chunks++;
- }
- else if ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id == RoQ_QUAD_CODEBOOK))
- {
- // if it's a quad VQ chunk following a codebook chunk, extend the last
- // chunk
- roq_data->chunks[roq_data->total_chunks - 1].chunk_size += (chunk_size + 8);
- stream_skip(demuxer->stream, chunk_size);
- }
- else if (!stream_eof(demuxer->stream))
- {
- mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Unknown RoQ chunk ID: %04X\n", chunk_id);
- }
-
- last_chunk_id = chunk_id;
- }
-
- // minimum output buffer size = largest audio chunk * 2, since each byte
- // in the DPCM encoding effectively represents 1 16-bit sample
- // (store it in wf->nBlockAlign for the time being since init_audio() will
- // step on it anyway)
- if (sh_audio)
- sh_audio->wf->nBlockAlign = largest_audio_chunk * 2;
-
- roq_data->current_chunk = 0;
-
- demuxer->priv = roq_data;
-
- stream_reset(demuxer->stream);
-
- return demuxer;
-}
-
-static void demux_close_roq(demuxer_t* demuxer) {
- roq_data_t *roq_data = demuxer->priv;
-
- free(roq_data);
-}
-
-
-const demuxer_desc_t demuxer_desc_roq = {
- "RoQ demuxer",
- "roq",
- "ROQ",
- "Mike Melanson",
- "",
- DEMUXER_TYPE_ROQ,
- 0, // unsafe autodetect
- roq_check_file,
- demux_roq_fill_buffer,
- demux_open_roq,
- demux_close_roq,
- NULL,
- NULL
-};
diff --git a/libmpdemux/demux_smjpeg.c b/libmpdemux/demux_smjpeg.c
deleted file mode 100644
index 8dabc8a0e2..0000000000
--- a/libmpdemux/demux_smjpeg.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * SMJPEG file parser
- * copyright (c) 2002 Alex Beregszaszi
- * based on text by Arpi (SMJPEG-format.txt) and later on
- * http://www.lokigames.com/development/download/smjpeg/SMJPEG.txt
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h> /* strtok */
-
-#include "config.h"
-#include "mp_msg.h"
-#include "libavutil/attributes.h"
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-static int smjpeg_check_file(demuxer_t* demuxer){
- int orig_pos = stream_tell(demuxer->stream);
- char buf[8];
- int version;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "Checking for SMJPEG\n");
-
- if (stream_read_word(demuxer->stream) == 0xA)
- {
- stream_read(demuxer->stream, buf, 6);
- buf[7] = 0;
-
- if (strncmp("SMJPEG", buf, 6)) {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Failed: SMJPEG\n");
- return 0;
- }
- }
- else
- return 0;
-
- version = stream_read_dword(demuxer->stream);
- if (version != 0)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Unknown version (%d) of SMJPEG. Please report!\n",
- version);
- return 0;
- }
-
- stream_seek(demuxer->stream, orig_pos);
-
- return DEMUXER_TYPE_SMJPEG;
-}
-
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_smjpeg_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
-{
- int dtype, dsize, dpts;
-
- demux->filepos = stream_tell(demux->stream);
-
- dtype = stream_read_dword_le(demux->stream);
- dpts = stream_read_dword(demux->stream);
- dsize = stream_read_dword(demux->stream);
-
- switch(dtype)
- {
- case mmioFOURCC('s','n','d','D'):
- /* fixme, but no decoder implemented yet */
- ds_read_packet(demux->audio, demux->stream, dsize,
- (float)dpts/1000.0, demux->filepos, 0);
- break;
- case mmioFOURCC('v','i','d','D'):
- ds_read_packet(demux->video, demux->stream, dsize,
- (float)dpts/1000.0, demux->filepos, 0);
- break;
- case mmioFOURCC('D','O','N','E'):
- return 1;
- default:
- return 0;
- }
-
- return 1;
-}
-
-static demuxer_t* demux_open_smjpeg(demuxer_t* demuxer){
- sh_video_t* sh_video;
- sh_audio_t* sh_audio;
- unsigned int htype = 0, hleng av_unused;
- int i = 0;
-
- /* file header */
- stream_skip(demuxer->stream, 8); /* \x00\x0aSMJPEG */
- stream_skip(demuxer->stream, 4);
-
- mp_msg(MSGT_DEMUX, MSGL_INFO, "This clip is %d seconds\n",
- stream_read_dword(demuxer->stream));
-
- /* stream header */
- while (i < 3)
- {
- i++;
- htype = stream_read_dword_le(demuxer->stream);
- if (htype == mmioFOURCC('H','E','N','D'))
- break;
- hleng = (stream_read_word(demuxer->stream)<<16)|stream_read_word(demuxer->stream);
- switch(htype)
- {
- case mmioFOURCC('_','V','I','D'):
- sh_video = new_sh_video(demuxer, 0);
- demuxer->video->sh = sh_video;
- sh_video->ds = demuxer->video;
-
- sh_video->bih = calloc(1, sizeof(*sh_video->bih));
-
- stream_skip(demuxer->stream, 4); /* number of frames */
-// sh_video->fps = 24;
-// sh_video->frametime = 1.0f/sh_video->fps;
- sh_video->disp_w = stream_read_word(demuxer->stream);
- sh_video->disp_h = stream_read_word(demuxer->stream);
- sh_video->format = stream_read_dword_le(demuxer->stream);
-
- /* these are false values */
- sh_video->bih->biSize = 40;
- sh_video->bih->biWidth = sh_video->disp_w;
- sh_video->bih->biHeight = sh_video->disp_h;
- sh_video->bih->biPlanes = 3;
- sh_video->bih->biBitCount = 12;
- sh_video->bih->biCompression = sh_video->format;
- sh_video->bih->biSizeImage = sh_video->disp_w*sh_video->disp_h;
- break;
- case mmioFOURCC('_','S','N','D'):
- sh_audio = new_sh_audio(demuxer, 0);
- demuxer->audio->id = 0;
- demuxer->audio->sh = sh_audio;
- sh_audio->ds = demuxer->audio;
-
- sh_audio->wf = calloc(1, sizeof(*sh_audio->wf));
-
- sh_audio->samplerate = stream_read_word(demuxer->stream);
- sh_audio->wf->wBitsPerSample = stream_read_char(demuxer->stream);
- sh_audio->channels = stream_read_char(demuxer->stream);
- sh_audio->format = stream_read_dword_le(demuxer->stream);
- sh_audio->wf->wFormatTag = sh_audio->format;
- sh_audio->wf->nChannels = sh_audio->channels;
- sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
- sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nChannels*
- sh_audio->wf->wBitsPerSample*sh_audio->wf->nSamplesPerSec/8;
- sh_audio->wf->nBlockAlign = sh_audio->channels *2;
- sh_audio->wf->cbSize = 0;
- break;
- case mmioFOURCC('_','T','X','T'):
- stream_skip(demuxer->stream, stream_read_dword(demuxer->stream));
- break;
- }
- }
-
- demuxer->seekable = 0;
-
- return demuxer;
-}
-
-static void demux_close_smjpeg(demuxer_t *demuxer)
-{
- return;
-}
-
-
-const demuxer_desc_t demuxer_desc_smjpeg = {
- "smjpeg demuxer",
- "smjpeg",
- "SMJPEG",
- "Alex Beregszasi",
- "",
- DEMUXER_TYPE_SMJPEG,
- 1, // safe autodetect
- smjpeg_check_file,
- demux_smjpeg_fill_buffer,
- demux_open_smjpeg,
- demux_close_smjpeg,
- NULL,
- NULL
-};
diff --git a/libmpdemux/demux_ts.c b/libmpdemux/demux_ts.c
deleted file mode 100644
index dbf12b7456..0000000000
--- a/libmpdemux/demux_ts.c
+++ /dev/null
@@ -1,3533 +0,0 @@
-/*
- * Demultiplexer for MPEG2 Transport Streams.
- *
- * Written by Nico <nsabbi@libero.it>
- * Kind feedback is appreciated; 'sucks' and alike is not.
- * Originally based on demux_pva.c written by Matteo Giani and FFmpeg (libavformat) sources
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "mp_msg.h"
-#include "options.h"
-
-#include "libmpcodecs/dec_audio.h"
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "parse_es.h"
-#include "stheader.h"
-#include "ms_hdr.h"
-#include "mpeg_hdr.h"
-#include "demux_ts.h"
-
-#define TS_PH_PACKET_SIZE 192
-#define TS_FEC_PACKET_SIZE 204
-#define TS_PACKET_SIZE 188
-#define NB_PID_MAX 8192
-
-#define MAX_HEADER_SIZE 6 /* enough for PES header + length */
-#define MAX_CHECK_SIZE 65535
-#define NUM_CONSECUTIVE_TS_PACKETS 32
-#define NUM_CONSECUTIVE_AUDIO_PACKETS 348
-#define MAX_A52_FRAME_SIZE 3840
-
-#ifndef SIZE_MAX
-#define SIZE_MAX ((size_t)-1)
-#endif
-
-#define TYPE_AUDIO 1
-#define TYPE_VIDEO 2
-#define TYPE_SUB 3
-
-int ts_prog;
-int ts_keep_broken=0;
-off_t ts_probe = 0;
-int audio_substream_id = -1;
-
-typedef enum
-{
- UNKNOWN = -1,
- VIDEO_MPEG1 = 0x10000001,
- VIDEO_MPEG2 = 0x10000002,
- VIDEO_MPEG4 = 0x10000004,
- VIDEO_H264 = 0x10000005,
- VIDEO_AVC = mmioFOURCC('a', 'v', 'c', '1'),
- VIDEO_DIRAC = mmioFOURCC('d', 'r', 'a', 'c'),
- VIDEO_VC1 = mmioFOURCC('W', 'V', 'C', '1'),
- AUDIO_MP2 = 0x50,
- AUDIO_A52 = 0x2000,
- AUDIO_DTS = 0x2001,
- AUDIO_LPCM_BE = 0x10001,
- AUDIO_AAC = mmioFOURCC('M', 'P', '4', 'A'),
- AUDIO_AAC_LATM = mmioFOURCC('M', 'P', '4', 'L'),
- AUDIO_TRUEHD = mmioFOURCC('T', 'R', 'H', 'D'),
- AUDIO_S302M = mmioFOURCC('B', 'S', 'S', 'D'),
- SPU_DVD = 0x3000000,
- SPU_DVB = 0x3000001,
- SPU_TELETEXT = 0x3000002,
- SPU_PGS = 0x3000003,
- PES_PRIVATE1 = 0xBD00000,
- SL_PES_STREAM = 0xD000000,
- SL_SECTION = 0xD100000,
- MP4_OD = 0xD200000,
-} es_stream_type_t;
-
-typedef struct {
- uint8_t *buffer;
- uint16_t buffer_len;
-} ts_section_t;
-
-typedef struct {
- int size;
- unsigned char *start;
- uint16_t payload_size;
- es_stream_type_t type, subtype;
- double pts, last_pts;
- int pid;
- char lang[4];
- int last_cc; // last cc code (-1 if first packet)
- int is_synced;
- ts_section_t section;
- uint8_t *extradata;
- int extradata_alloc, extradata_len;
- struct {
- uint8_t au_start, au_end, last_au_end;
- } sl;
-} ES_stream_t;
-
-typedef struct {
- void *sh;
- int id;
- int type;
-} sh_av_t;
-
-typedef struct MpegTSContext {
- int packet_size; // raw packet size, including FEC if present e.g. 188 bytes
- ES_stream_t *pids[NB_PID_MAX];
- sh_av_t streams[NB_PID_MAX];
-} MpegTSContext;
-
-
-typedef struct {
- demux_stream_t *ds;
- demux_packet_t *pack;
- int offset, buffer_size;
-} av_fifo_t;
-
-#define MAX_EXTRADATA_SIZE 64*1024
-typedef struct {
- int32_t object_type; //aka codec used
- int32_t stream_type; //video, audio etc.
- uint8_t buf[MAX_EXTRADATA_SIZE];
- uint16_t buf_size;
- uint8_t szm1;
-} mp4_decoder_config_t;
-
-typedef struct {
- //flags
- uint8_t flags;
- uint8_t au_start;
- uint8_t au_end;
- uint8_t random_accesspoint;
- uint8_t random_accesspoint_only;
- uint8_t padding;
- uint8_t use_ts;
- uint8_t idle;
- uint8_t duration;
-
- uint32_t ts_resolution, ocr_resolution;
- uint8_t ts_len, ocr_len, au_len, instant_bitrate_len, degr_len, au_seqnum_len, packet_seqnum_len;
- uint32_t timescale;
- uint16_t au_duration, cts_duration;
- uint64_t ocr, dts, cts;
-} mp4_sl_config_t;
-
-typedef struct {
- uint16_t id;
- uint8_t flags;
- mp4_decoder_config_t decoder;
- mp4_sl_config_t sl;
-} mp4_es_descr_t;
-
-typedef struct {
- uint16_t id;
- uint8_t flags;
- mp4_es_descr_t *es;
- uint16_t es_cnt;
-} mp4_od_t;
-
-typedef struct {
- uint8_t skip;
- uint8_t table_id;
- uint8_t ssi;
- uint16_t section_length;
- uint16_t ts_id;
- uint8_t version_number;
- uint8_t curr_next;
- uint8_t section_number;
- uint8_t last_section_number;
- struct pat_progs_t {
- uint16_t id;
- uint16_t pmt_pid;
- } *progs;
- uint16_t progs_cnt;
- ts_section_t section;
-} pat_t;
-
-typedef struct {
- uint16_t progid;
- uint8_t skip;
- uint8_t table_id;
- uint8_t ssi;
- uint16_t section_length;
- uint8_t version_number;
- uint8_t curr_next;
- uint8_t section_number;
- uint8_t last_section_number;
- uint16_t PCR_PID;
- uint16_t prog_descr_length;
- ts_section_t section;
- uint16_t es_cnt;
- struct pmt_es_t {
- uint16_t pid;
- uint32_t type; //it's 8 bit long, but cast to the right type as FOURCC
- uint16_t descr_length;
- uint8_t format_descriptor[5];
- uint8_t lang[4];
- uint16_t mp4_es_id;
- } *es;
- mp4_od_t iod, *od;
- mp4_es_descr_t *mp4es;
- int od_cnt, mp4es_cnt;
-} pmt_t;
-
-typedef struct {
- uint64_t size;
- float duration;
- double first_pts;
- double last_pts;
-} TS_stream_info;
-
-typedef struct {
- MpegTSContext ts;
- int last_pid;
- av_fifo_t fifo[3]; //0 for audio, 1 for video, 2 for subs
- pat_t pat;
- pmt_t *pmt;
- uint16_t pmt_cnt;
- uint32_t prog;
- uint32_t vbitrate;
- int keep_broken;
- int last_aid;
- int last_vid;
- int last_sid;
- char packet[TS_FEC_PACKET_SIZE];
- TS_stream_info vstr, astr;
-} ts_priv_t;
-
-
-typedef struct {
- es_stream_type_t type;
- ts_section_t section;
-} TS_pids_t;
-
-
-static int IS_AUDIO(es_stream_type_t type)
-{
- switch (type) {
- case AUDIO_MP2:
- case AUDIO_A52:
- case AUDIO_LPCM_BE:
- case AUDIO_AAC:
- case AUDIO_AAC_LATM:
- case AUDIO_DTS:
- case AUDIO_TRUEHD:
- case AUDIO_S302M:
- return 1;
- }
- return 0;
-}
-
-static int IS_VIDEO(es_stream_type_t type)
-{
- switch (type) {
- case VIDEO_MPEG1:
- case VIDEO_MPEG2:
- case VIDEO_MPEG4:
- case VIDEO_H264:
- case VIDEO_AVC:
- case VIDEO_DIRAC:
- case VIDEO_VC1:
- return 1;
- }
- return 0;
-}
-
-static int IS_SUB(es_stream_type_t type)
-{
- switch (type) {
- case SPU_DVD:
- case SPU_DVB:
- case SPU_PGS:
- case SPU_TELETEXT:
- return 1;
- }
- return 0;
-}
-
-static int ts_parse(demuxer_t *demuxer, ES_stream_t *es, unsigned char *packet, int probe);
-
-static uint8_t get_packet_size(const unsigned char *buf, int size)
-{
- int i;
-
- if (size < (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS))
- return 0;
-
- for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)
- {
- if (buf[i * TS_PACKET_SIZE] != 0x47)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]);
- goto try_fec;
- }
- }
- return TS_PACKET_SIZE;
-
-try_fec:
- for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)
- {
- if (buf[i * TS_FEC_PACKET_SIZE] != 0x47){
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]);
- goto try_philips;
- }
- }
- return TS_FEC_PACKET_SIZE;
-
- try_philips:
- for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)
- {
- if (buf[i * TS_PH_PACKET_SIZE] != 0x47)
- return 0;
- }
- return TS_PH_PACKET_SIZE;
-}
-
-static int parse_avc_sps(uint8_t *buf, int len, int *w, int *h);
-static inline uint8_t *pid_lang_from_pmt(ts_priv_t *priv, int pid);
-
-static void ts_add_stream(demuxer_t * demuxer, ES_stream_t *es)
-{
- int i;
- ts_priv_t *priv = (ts_priv_t*) demuxer->priv;
-
- if(priv->ts.streams[es->pid].sh)
- return;
-
- if((IS_AUDIO(es->type) || IS_AUDIO(es->subtype)) && priv->last_aid+1 < MAX_A_STREAMS)
- {
- sh_audio_t *sh = new_sh_audio_aid(demuxer, priv->last_aid, es->pid);
- if(sh)
- {
- const char *lang = pid_lang_from_pmt(priv, es->pid);
- sh->needs_parsing = 1;
- sh->format = IS_AUDIO(es->type) ? es->type : es->subtype;
- sh->ds = demuxer->audio;
-
- priv->ts.streams[es->pid].id = priv->last_aid;
- priv->ts.streams[es->pid].sh = sh;
- priv->ts.streams[es->pid].type = TYPE_AUDIO;
- mp_msg(MSGT_DEMUX, MSGL_V, "\r\nADDED AUDIO PID %d, type: %x stream n. %d\r\n", es->pid, sh->format, priv->last_aid);
- if (lang && lang[0])
- mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_AID_%d_LANG=%s\n", es->pid, lang);
- priv->last_aid++;
- }
-
- if(es->extradata && es->extradata_len)
- {
- sh->wf = malloc(sizeof(*sh->wf) + es->extradata_len);
- sh->wf->cbSize = es->extradata_len;
- memcpy(sh->wf + 1, es->extradata, es->extradata_len);
- }
- }
-
- if((IS_VIDEO(es->type) || IS_VIDEO(es->subtype)) && priv->last_vid+1 < MAX_V_STREAMS)
- {
- sh_video_t *sh = new_sh_video_vid(demuxer, priv->last_vid, es->pid);
- if(sh)
- {
- sh->format = IS_VIDEO(es->type) ? es->type : es->subtype;
- sh->ds = demuxer->video;
-
- priv->ts.streams[es->pid].id = priv->last_vid;
- priv->ts.streams[es->pid].sh = sh;
- priv->ts.streams[es->pid].type = TYPE_VIDEO;
- mp_msg(MSGT_DEMUX, MSGL_V, "\r\nADDED VIDEO PID %d, type: %x stream n. %d\r\n", es->pid, sh->format, priv->last_vid);
- priv->last_vid++;
-
-
- if(sh->format == VIDEO_AVC && es->extradata && es->extradata_len)
- {
- int w = 0, h = 0;
- sh->bih = calloc(1, sizeof(*sh->bih) + es->extradata_len);
- sh->bih->biSize= sizeof(*sh->bih) + es->extradata_len;
- sh->bih->biCompression = sh->format;
- memcpy(sh->bih + 1, es->extradata, es->extradata_len);
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "EXTRADATA(%d BYTES): \n", es->extradata_len);
- for(i = 0;i < es->extradata_len; i++)
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "%02x ", (int) es->extradata[i]);
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\n");
- if(parse_avc_sps(es->extradata, es->extradata_len, &w, &h))
- {
- sh->bih->biWidth = w;
- sh->bih->biHeight = h;
- }
- }
- }
- }
-
- if(IS_SUB(es->type) && priv->last_sid+1 < MAX_S_STREAMS)
- {
- sh_sub_t *sh = new_sh_sub_sid_lang(demuxer, priv->last_sid, es->pid, pid_lang_from_pmt(priv, es->pid));
- if (sh) {
- switch (es->type) {
- case SPU_DVB:
- sh->type = 'b'; break;
- case SPU_DVD:
- sh->type = 'v'; break;
- case SPU_PGS:
- sh->type = 'p'; break;
- }
- priv->ts.streams[es->pid].id = priv->last_sid;
- priv->ts.streams[es->pid].sh = sh;
- priv->ts.streams[es->pid].type = TYPE_SUB;
- priv->last_sid++;
- }
- }
-}
-
-static int ts_check_file(demuxer_t * demuxer)
-{
- const int buf_size = (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS);
- unsigned char buf[TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS], done = 0, *ptr;
- uint32_t _read, i, count = 0, is_ts;
- int cc[NB_PID_MAX], last_cc[NB_PID_MAX], pid, cc_ok, c, good, bad;
- uint8_t size = 0;
- off_t pos = 0;
- off_t init_pos;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "Checking for MPEG-TS...\n");
-
- init_pos = stream_tell(demuxer->stream);
- is_ts = 0;
- while(! done)
- {
- i = 1;
- c = 0;
-
- while(((c=stream_read_char(demuxer->stream)) != 0x47)
- && (c >= 0)
- && (i < MAX_CHECK_SIZE)
- && ! demuxer->stream->eof
- ) i++;
-
-
- if(c != 0x47)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "THIS DOESN'T LOOK LIKE AN MPEG-TS FILE!\n");
- is_ts = 0;
- done = 1;
- continue;
- }
-
- pos = stream_tell(demuxer->stream) - 1;
- buf[0] = c;
- _read = stream_read(demuxer->stream, &buf[1], buf_size-1);
-
- if(_read < buf_size-1)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "COULDN'T READ ENOUGH DATA, EXITING TS_CHECK\n");
- stream_reset(demuxer->stream);
- return 0;
- }
-
- size = get_packet_size(buf, buf_size);
- if(size)
- {
- done = 1;
- is_ts = 1;
- }
-
- if(pos - init_pos >= MAX_CHECK_SIZE)
- {
- done = 1;
- is_ts = 0;
- }
- }
-
- mp_msg(MSGT_DEMUX, MSGL_V, "TRIED UP TO POSITION %"PRIu64", FOUND %x, packet_size= %d, SEEMS A TS? %d\n", (uint64_t) pos, c, size, is_ts);
- stream_seek(demuxer->stream, pos);
-
- if(! is_ts)
- return 0;
-
- //LET'S CHECK continuity counters
- good = bad = 0;
- for(count = 0; count < NB_PID_MAX; count++)
- {
- cc[count] = last_cc[count] = -1;
- }
-
- for(count = 0; count < NUM_CONSECUTIVE_TS_PACKETS; count++)
- {
- ptr = &(buf[size * count]);
- pid = ((ptr[1] & 0x1f) << 8) | ptr[2];
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "BUF: %02x %02x %02x %02x, PID %d, SIZE: %d \n",
- ptr[0], ptr[1], ptr[2], ptr[3], pid, size);
-
- if((pid == 8191) || (pid < 16))
- continue;
-
- cc[pid] = (ptr[3] & 0xf);
- cc_ok = (last_cc[pid] < 0) || ((((last_cc[pid] + 1) & 0x0f) == cc[pid]));
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "PID %d, COMPARE CC %d AND LAST_CC %d\n", pid, cc[pid], last_cc[pid]);
- if(! cc_ok)
- //return 0;
- bad++;
- else
- good++;
-
- last_cc[pid] = cc[pid];
- }
-
- mp_msg(MSGT_DEMUX, MSGL_V, "GOOD CC: %d, BAD CC: %d\n", good, bad);
-
- if(good >= bad)
- return size;
- else
- return 0;
-}
-
-
-static inline int32_t progid_idx_in_pmt(ts_priv_t *priv, uint16_t progid)
-{
- int x;
-
- if(priv->pmt == NULL)
- return -1;
-
- for(x = 0; x < priv->pmt_cnt; x++)
- {
- if(priv->pmt[x].progid == progid)
- return x;
- }
-
- return -1;
-}
-
-
-static inline int32_t progid_for_pid(ts_priv_t *priv, int pid, int32_t req) //finds the first program listing a pid
-{
- int i, j;
- pmt_t *pmt;
-
-
- if(priv->pmt == NULL)
- return -1;
-
-
- for(i=0; i < priv->pmt_cnt; i++)
- {
- pmt = &(priv->pmt[i]);
-
- if(pmt->es == NULL)
- return -1;
-
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(pmt->es[j].pid == pid)
- {
- if((req == 0) || (req == pmt->progid))
- return pmt->progid;
- }
- }
-
- }
- return -1;
-}
-
-static inline int32_t prog_pcr_pid(ts_priv_t *priv, int progid)
-{
- int i;
-
- if(priv->pmt == NULL)
- return -1;
- for(i=0; i < priv->pmt_cnt; i++)
- {
- if(priv->pmt[i].progid == progid)
- return priv->pmt[i].PCR_PID;
- }
- return -1;
-}
-
-
-static inline int pid_match_lang(ts_priv_t *priv, uint16_t pid, char *lang)
-{
- uint16_t i, j;
- pmt_t *pmt;
-
- if(priv->pmt == NULL)
- return -1;
-
- for(i=0; i < priv->pmt_cnt; i++)
- {
- pmt = &(priv->pmt[i]);
-
- if(pmt->es == NULL)
- return -1;
-
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(pmt->es[j].pid != pid)
- continue;
-
- mp_msg(MSGT_DEMUXER, MSGL_V, "CMP LANG %s AND %s, pids: %d %d\n",pmt->es[j].lang, lang, pmt->es[j].pid, pid);
- if(strncmp(pmt->es[j].lang, lang, 3) == 0)
- {
- return 1;
- }
- }
-
- }
-
- return -1;
-}
-
-typedef struct {
- int32_t atype, vtype, stype; //types
- int32_t apid, vpid, spid; //stream ids
- char alang[4]; //languages
- uint16_t prog;
- off_t probe;
-} tsdemux_init_t;
-
-//second stage: returns the count of A52 syncwords found
-static int a52_check(char *buf, int len)
-{
- int cnt, frame_length = 0, ok, srate;
-
- cnt = ok = 0;
- if(len < 8)
- return 0;
-
- while(cnt < len - 7)
- {
- if(buf[cnt] == 0x0B && buf[cnt+1] == 0x77)
- {
- frame_length = mp_a52_framesize(&buf[cnt], &srate);
- if(frame_length>=7 && frame_length<=3840)
- {
- cnt += frame_length;
- ok++;
- }
- else
- cnt++;
- }
- else
- cnt++;
- }
-
- mp_msg(MSGT_DEMUXER, MSGL_V, "A52_CHECK(%d input bytes), found %d frame syncwords of %d bytes length\n", len, ok, frame_length);
- return ok;
-}
-
-
-static off_t ts_detect_streams(demuxer_t *demuxer, tsdemux_init_t *param)
-{
- int video_found = 0, audio_found = 0, i, num_packets = 0, req_apid, req_vpid, req_spid;
- int is_audio, is_video, is_sub, has_tables;
- int32_t p, chosen_pid = 0;
- off_t pos=0, ret = 0, init_pos, end_pos;
- ES_stream_t es;
- unsigned char tmp[TS_FEC_PACKET_SIZE];
- ts_priv_t *priv = (ts_priv_t*) demuxer->priv;
- struct {
- char *buf;
- int pos;
- } pes_priv1[8192], *pptr;
- char *tmpbuf;
-
- priv->last_pid = 8192; //invalid pid
-
- req_apid = param->apid;
- req_vpid = param->vpid;
- req_spid = param->spid;
-
- has_tables = 0;
- memset(pes_priv1, 0, sizeof(pes_priv1));
- init_pos = stream_tell(demuxer->stream);
- mp_msg(MSGT_DEMUXER, MSGL_V, "PROBING UP TO %"PRIu64", PROG: %d\n", (uint64_t) param->probe, param->prog);
- end_pos = init_pos + (param->probe ? param->probe : TS_MAX_PROBE_SIZE);
- while(1)
- {
- pos = stream_tell(demuxer->stream);
- if(pos > end_pos || demuxer->stream->eof)
- break;
-
- if(ts_parse(demuxer, &es, tmp, 1))
- {
- //Non PES-aligned A52 audio may escape detection if PMT is not present;
- //in this case we try to find at least 3 A52 syncwords
- if((es.type == PES_PRIVATE1) && (! audio_found) && req_apid > -2)
- {
- pptr = &pes_priv1[es.pid];
- if(pptr->pos < 64*1024)
- {
- tmpbuf = realloc(pptr->buf, pptr->pos + es.size);
- if(tmpbuf != NULL)
- {
- pptr->buf = tmpbuf;
- memcpy(&(pptr->buf[ pptr->pos ]), es.start, es.size);
- pptr->pos += es.size;
- if(a52_check(pptr->buf, pptr->pos) > 2)
- {
- param->atype = AUDIO_A52;
- param->apid = es.pid;
- es.type = AUDIO_A52;
- }
- }
- }
- }
-
- is_audio = IS_AUDIO(es.type) || ((es.type==SL_PES_STREAM) && IS_AUDIO(es.subtype));
- is_video = IS_VIDEO(es.type) || ((es.type==SL_PES_STREAM) && IS_VIDEO(es.subtype));
- is_sub = IS_SUB(es.type);
-
-
- if((! is_audio) && (! is_video) && (! is_sub))
- continue;
- if(is_audio && req_apid==-2)
- continue;
-
- if(is_video)
- {
- chosen_pid = (req_vpid == es.pid);
- if((! chosen_pid) && (req_vpid > 0))
- continue;
- }
- else if(is_audio)
- {
- if(req_apid > 0)
- {
- chosen_pid = (req_apid == es.pid);
- if(! chosen_pid)
- continue;
- }
- else if(param->alang[0] > 0 && es.lang[0] > 0)
- {
- if(pid_match_lang(priv, es.pid, param->alang) == -1)
- continue;
-
- chosen_pid = 1;
- param->apid = req_apid = es.pid;
- }
- }
- else if(is_sub)
- {
- chosen_pid = (req_spid == es.pid);
- if((! chosen_pid) && (req_spid > 0))
- continue;
- }
-
- if(req_apid < 0 && (param->alang[0] == 0) && req_vpid < 0 && req_spid < 0)
- chosen_pid = 1;
-
- if((ret == 0) && chosen_pid)
- {
- ret = stream_tell(demuxer->stream);
- }
-
- p = progid_for_pid(priv, es.pid, param->prog);
- if(p != -1)
- {
- has_tables++;
- if(!param->prog && chosen_pid)
- param->prog = p;
- }
-
- if((param->prog > 0) && (param->prog != p))
- {
- if(audio_found)
- {
- if(is_video && (req_vpid == es.pid))
- {
- param->vtype = IS_VIDEO(es.type) ? es.type : es.subtype;
- param->vpid = es.pid;
- video_found = 1;
- break;
- }
- }
-
- if(video_found)
- {
- if(is_audio && (req_apid == es.pid))
- {
- param->atype = IS_AUDIO(es.type) ? es.type : es.subtype;
- param->apid = es.pid;
- audio_found = 1;
- break;
- }
- }
-
-
- continue;
- }
-
-
- mp_msg(MSGT_DEMUXER, MSGL_DBG2, "TYPE: %x, PID: %d, PROG FOUND: %d\n", es.type, es.pid, param->prog);
-
-
- if(is_video)
- {
- if((req_vpid == -1) || (req_vpid == es.pid))
- {
- param->vtype = IS_VIDEO(es.type) ? es.type : es.subtype;
- param->vpid = es.pid;
- video_found = 1;
- }
- }
-
-
- if(((req_vpid == -2) || (num_packets >= NUM_CONSECUTIVE_AUDIO_PACKETS)) && audio_found && !param->probe)
- {
- //novideo or we have at least 348 audio packets (64 KB) without video (TS with audio only)
- param->vtype = 0;
- break;
- }
-
- if(is_sub)
- {
- if((req_spid == -1) || (req_spid == es.pid))
- {
- param->stype = es.type;
- param->spid = es.pid;
- }
- }
-
- if(is_audio)
- {
- if((req_apid == -1) || (req_apid == es.pid))
- {
- param->atype = IS_AUDIO(es.type) ? es.type : es.subtype;
- param->apid = es.pid;
- audio_found = 1;
- }
- }
-
- if(audio_found && (param->apid == es.pid) && (! video_found))
- num_packets++;
-
- if((has_tables==0) && (video_found && audio_found) && (pos >= 1000000))
- break;
- }
- }
-
- for(i=0; i<8192; i++)
- {
- if(pes_priv1[i].buf != NULL)
- {
- free(pes_priv1[i].buf);
- pes_priv1[i].buf = NULL;
- pes_priv1[i].pos = 0;
- }
- }
-
- if(video_found)
- {
- if(param->vtype == VIDEO_MPEG1)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG1(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_MPEG2)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG2(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_MPEG4)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG4(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_H264)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO H264(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_VC1)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO VC1(pid=%d) ", param->vpid);
- else if(param->vtype == VIDEO_AVC)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO AVC(NAL-H264, pid=%d) ", param->vpid);
- }
- else
- {
- param->vtype = UNKNOWN;
- //WE DIDN'T MATCH ANY VIDEO STREAM
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO VIDEO! ");
- }
-
- if(param->atype == AUDIO_MP2)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MPA(pid=%d)", param->apid);
- else if(param->atype == AUDIO_A52)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO A52(pid=%d)", param->apid);
- else if(param->atype == AUDIO_DTS)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO DTS(pid=%d)", param->apid);
- else if(param->atype == AUDIO_LPCM_BE)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO LPCM(pid=%d)", param->apid);
- else if(param->atype == AUDIO_AAC)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO AAC(pid=%d)", param->apid);
- else if(param->atype == AUDIO_AAC_LATM)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO AAC LATM(pid=%d)", param->apid);
- else if(param->atype == AUDIO_TRUEHD)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO TRUEHD(pid=%d)", param->apid);
- else if(param->atype == AUDIO_S302M)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO S302M(pid=%d)", param->apid);
- else
- {
- audio_found = 0;
- param->atype = UNKNOWN;
- //WE DIDN'T MATCH ANY AUDIO STREAM, SO WE FORCE THE DEMUXER TO IGNORE AUDIO
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO AUDIO! (try increasing -tsprobe)");
- }
-
- if(IS_SUB(param->stype))
- mp_msg(MSGT_DEMUXER, MSGL_INFO, " SUB %s(pid=%d) ", (param->stype==SPU_DVD ? "DVD" : param->stype==SPU_DVB ? "DVB" : "Teletext"), param->spid);
- else
- {
- param->stype = UNKNOWN;
- mp_msg(MSGT_DEMUXER, MSGL_INFO, " NO SUBS (yet)! ");
- }
-
- if(video_found || audio_found)
- {
- if(!param->prog)
- {
- p = progid_for_pid(priv, video_found ? param->vpid : param->apid, 0);
- if(p != -1)
- param->prog = p;
- }
-
- if(demuxer->stream->eof && (ret == 0))
- ret = init_pos;
- mp_msg(MSGT_DEMUXER, MSGL_INFO, " PROGRAM N. %d\n", param->prog);
- }
- else
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "\n");
-
-
- for(i=0; i<NB_PID_MAX; i++)
- {
- if(priv->ts.pids[i] != NULL)
- {
- priv->ts.pids[i]->payload_size = 0;
- priv->ts.pids[i]->pts = priv->ts.pids[i]->last_pts = 0;
- priv->ts.pids[i]->last_cc = -1;
- priv->ts.pids[i]->is_synced = 0;
- }
- }
-
- return ret;
-}
-
-static int parse_avc_sps(uint8_t *buf, int len, int *w, int *h)
-{
- int sps, sps_len;
- unsigned char *ptr;
- mp_mpeg_header_t picture;
- if(len < 6)
- return 0;
- sps = buf[5] & 0x1f;
- if(!sps)
- return 0;
- sps_len = (buf[6] << 8) | buf[7];
- if(!sps_len || (sps_len > len - 8))
- return 0;
- ptr = &(buf[8]);
- picture.display_picture_width = picture.display_picture_height = 0;
- h264_parse_sps(&picture, ptr, len - 8);
- if(!picture.display_picture_width || !picture.display_picture_height)
- return 0;
- *w = picture.display_picture_width;
- *h = picture.display_picture_height;
- return 1;
-}
-
-static demuxer_t *demux_open_ts(demuxer_t * demuxer)
-{
- int i;
- uint8_t packet_size;
- sh_video_t *sh_video;
- sh_audio_t *sh_audio;
- off_t start_pos;
- tsdemux_init_t params;
- ts_priv_t * priv = demuxer->priv;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "DEMUX OPEN, AUDIO_ID: %d, VIDEO_ID: %d, SUBTITLE_ID: %d,\n",
- demuxer->audio->id, demuxer->video->id, demuxer->sub->id);
-
-
- demuxer->type= DEMUXER_TYPE_MPEG_TS;
-
-
- stream_reset(demuxer->stream);
-
- packet_size = ts_check_file(demuxer);
- if(!packet_size)
- return NULL;
-
- priv = calloc(1, sizeof(ts_priv_t));
- if(priv == NULL)
- {
- mp_msg(MSGT_DEMUX, MSGL_FATAL, "DEMUX_OPEN_TS, couldn't allocate enough memory for ts->priv, exit\n");
- return NULL;
- }
-
- for(i=0; i < NB_PID_MAX; i++)
- {
- priv->ts.pids[i] = NULL;
- priv->ts.streams[i].id = -3;
- }
- priv->pat.progs = NULL;
- priv->pat.progs_cnt = 0;
- priv->pat.section.buffer = NULL;
- priv->pat.section.buffer_len = 0;
-
- priv->pmt = NULL;
- priv->pmt_cnt = 0;
-
- priv->keep_broken = ts_keep_broken;
- priv->ts.packet_size = packet_size;
-
-
- demuxer->priv = priv;
- if(demuxer->stream->type != STREAMTYPE_FILE)
- demuxer->seekable = 1;
- else
- demuxer->seekable = 1;
-
-
- params.atype = params.vtype = params.stype = UNKNOWN;
- params.apid = demuxer->audio->id;
- params.vpid = demuxer->video->id;
- params.spid = demuxer->sub->id;
- params.prog = ts_prog;
- params.probe = ts_probe;
-
- if(demuxer->opts->audio_lang != NULL)
- {
- strncpy(params.alang, demuxer->opts->audio_lang[0], 3);
- params.alang[3] = 0;
- }
- else
- memset(params.alang, 0, 4);
-
- start_pos = ts_detect_streams(demuxer, &params);
-
- demuxer->sub->id = params.spid;
- priv->prog = params.prog;
-
- if(params.vtype != UNKNOWN)
- {
- ts_add_stream(demuxer, priv->ts.pids[params.vpid]);
- sh_video = priv->ts.streams[params.vpid].sh;
- demuxer->video->id = priv->ts.streams[params.vpid].id;
- sh_video->ds = demuxer->video;
- sh_video->format = params.vtype;
- demuxer->video->sh = sh_video;
- }
-
- if(params.atype != UNKNOWN)
- {
- ES_stream_t *es = priv->ts.pids[params.apid];
-
- if(!IS_AUDIO(es->type) && !IS_AUDIO(es->subtype) && IS_AUDIO(params.atype)) es->subtype = params.atype;
- ts_add_stream(demuxer, priv->ts.pids[params.apid]);
- sh_audio = priv->ts.streams[params.apid].sh;
- demuxer->audio->id = priv->ts.streams[params.apid].id;
- sh_audio->ds = demuxer->audio;
- sh_audio->format = params.atype;
- demuxer->audio->sh = sh_audio;
- }
-
-
- mp_msg(MSGT_DEMUXER,MSGL_V, "Opened TS demuxer, audio: %x(pid %d), video: %x(pid %d)...POS=%"PRIu64", PROBE=%"PRIu64"\n", params.atype, demuxer->audio->id, params.vtype, demuxer->video->id, (uint64_t) start_pos, ts_probe);
-
-
- start_pos = start_pos <= priv->ts.packet_size ?
- demuxer->stream->start_pos :
- start_pos - priv->ts.packet_size;
- demuxer->movi_start = start_pos;
- demuxer->reference_clock = MP_NOPTS_VALUE;
- stream_reset(demuxer->stream);
- stream_seek(demuxer->stream, start_pos); //IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES?
-
-
- priv->last_pid = 8192; //invalid pid
-
- for(i = 0; i < 3; i++)
- {
- priv->fifo[i].pack = NULL;
- priv->fifo[i].offset = 0;
- }
- priv->fifo[0].ds = demuxer->audio;
- priv->fifo[1].ds = demuxer->video;
- priv->fifo[2].ds = demuxer->sub;
-
- priv->fifo[0].buffer_size = 1536;
- priv->fifo[1].buffer_size = 32767;
- priv->fifo[2].buffer_size = 32767;
-
- priv->pat.section.buffer_len = 0;
- for(i = 0; i < priv->pmt_cnt; i++)
- priv->pmt[i].section.buffer_len = 0;
-
- demuxer->filepos = stream_tell(demuxer->stream);
- return demuxer;
-}
-
-static void demux_close_ts(demuxer_t * demuxer)
-{
- uint16_t i;
- ts_priv_t *priv = (ts_priv_t*) demuxer->priv;
-
- if(priv)
- {
- free(priv->pat.section.buffer);
- free(priv->pat.progs);
-
- if(priv->pmt)
- {
- for(i = 0; i < priv->pmt_cnt; i++)
- {
- free(priv->pmt[i].section.buffer);
- free(priv->pmt[i].es);
- }
- free(priv->pmt);
- }
- for (i = 0; i < NB_PID_MAX; i++)
- {
- free(priv->ts.pids[i]);
- priv->ts.pids[i] = NULL;
- }
- for (i = 0; i < 3; i++)
- {
- if (priv->fifo[i].pack)
- free_demux_packet(priv->fifo[i].pack);
- priv->fifo[i].pack = NULL;
- }
- free(priv);
- }
- demuxer->priv=NULL;
-}
-
-
-#define getbits mp_getbits
-
-static int mp4_parse_sl_packet(pmt_t *pmt, uint8_t *buf, uint16_t packet_len, int pid, ES_stream_t *pes_es)
-{
- int i, n, m, mp4_es_id = -1;
- uint64_t v = 0;
- uint32_t pl_size = 0;
- int deg_flag = 0;
- mp4_es_descr_t *es = NULL;
- mp4_sl_config_t *sl = NULL;
- uint8_t au_start = 0, au_end = 0, rap_flag = 0, ocr_flag = 0, padding = 0, padding_bits = 0, idle = 0;
-
- pes_es->is_synced = 0;
- mp_msg(MSGT_DEMUXER,MSGL_V, "mp4_parse_sl_packet, pid: %d, pmt: %pm, packet_len: %d\n", pid, pmt, packet_len);
- if(! pmt || !packet_len)
- return 0;
-
- for(i = 0; i < pmt->es_cnt; i++)
- {
- if(pmt->es[i].pid == pid)
- mp4_es_id = pmt->es[i].mp4_es_id;
- }
- if(mp4_es_id < 0)
- return -1;
-
- for(i = 0; i < pmt->mp4es_cnt; i++)
- {
- if(pmt->mp4es[i].id == mp4_es_id)
- es = &(pmt->mp4es[i]);
- }
- if(! es)
- return -1;
-
- pes_es->subtype = es->decoder.object_type;
-
- sl = &(es->sl);
- if(!sl)
- return -1;
-
- //now es is the complete es_descriptor of out mp4 ES stream
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "ID: %d, FLAGS: 0x%x, subtype: %x\n", es->id, sl->flags, pes_es->subtype);
-
- n = 0;
- if(sl->au_start)
- pes_es->sl.au_start = au_start = getbits(buf, n++, 1);
- else
- pes_es->sl.au_start = (pes_es->sl.last_au_end ? 1 : 0);
- if(sl->au_end)
- pes_es->sl.au_end = au_end = getbits(buf, n++, 1);
-
- if(!sl->au_start && !sl->au_end)
- {
- pes_es->sl.au_start = pes_es->sl.au_end = au_start = au_end = 1;
- }
- pes_es->sl.last_au_end = pes_es->sl.au_end;
-
-
- if(sl->ocr_len > 0)
- ocr_flag = getbits(buf, n++, 1);
- if(sl->idle)
- idle = getbits(buf, n++, 1);
- if(sl->padding)
- padding = getbits(buf, n++, 1);
- if(padding)
- {
- padding_bits = getbits(buf, n, 3);
- n += 3;
- }
-
- if(idle || (padding && !padding_bits))
- {
- pes_es->payload_size = 0;
- return -1;
- }
-
- //(! idle && (!padding || padding_bits != 0)) is true
- n += sl->packet_seqnum_len;
- if(sl->degr_len)
- deg_flag = getbits(buf, n++, 1);
- if(deg_flag)
- n += sl->degr_len;
-
- if(ocr_flag)
- {
- n += sl->ocr_len;
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "OCR: %d bits\n", sl->ocr_len);
- }
-
- if(packet_len * 8 <= n)
- return -1;
-
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "\nAU_START: %d, AU_END: %d\n", au_start, au_end);
- if(au_start)
- {
- int dts_flag = 0, cts_flag = 0, ib_flag = 0;
-
- if(sl->random_accesspoint)
- rap_flag = getbits(buf, n++, 1);
-
- //check commented because it seems it's rarely used, and we need this flag set in case of au_start
- //the decoder will eventually discard the payload if it can't decode it
- //if(rap_flag || sl->random_accesspoint_only)
- pes_es->is_synced = 1;
-
- n += sl->au_seqnum_len;
- if(packet_len * 8 <= n+8)
- return -1;
- if(sl->use_ts)
- {
- dts_flag = getbits(buf, n++, 1);
- cts_flag = getbits(buf, n++, 1);
- }
- if(sl->instant_bitrate_len)
- ib_flag = getbits(buf, n++, 1);
- if(packet_len * 8 <= n+8)
- return -1;
- if(dts_flag && (sl->ts_len > 0))
- {
- n += sl->ts_len;
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "DTS: %d bits\n", sl->ts_len);
- }
- if(packet_len * 8 <= n+8)
- return -1;
- if(cts_flag && (sl->ts_len > 0))
- {
- int i = 0, m;
-
- while(i < sl->ts_len)
- {
- m = FFMIN(8, sl->ts_len - i);
- v |= getbits(buf, n, m);
- if(sl->ts_len - i > 8)
- v <<= 8;
- i += m;
- n += m;
- if(packet_len * 8 <= n+8)
- return -1;
- }
-
- pes_es->pts = (double) v / (double) sl->ts_resolution;
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "CTS: %d bits, value: %"PRIu64"/%d = %.3f\n", sl->ts_len, v, sl->ts_resolution, pes_es->pts);
- }
-
-
- i = 0;
- pl_size = 0;
- while(i < sl->au_len)
- {
- m = FFMIN(8, sl->au_len - i);
- pl_size |= getbits(buf, n, m);
- if(sl->au_len - i > 8)
- pl_size <<= 8;
- i += m;
- n += m;
- if(packet_len * 8 <= n+8)
- return -1;
- }
- mp_msg(MSGT_DEMUXER,MSGL_DBG2, "AU_LEN: %u (%d bits)\n", pl_size, sl->au_len);
- if(ib_flag)
- n += sl->instant_bitrate_len;
- }
-
- m = (n+7)/8;
- if(0 < pl_size && pl_size < pes_es->payload_size)
- pes_es->payload_size = pl_size;
-
- mp_msg(MSGT_DEMUXER,MSGL_V, "mp4_parse_sl_packet, n=%d, m=%d, size from pes hdr: %u, sl hdr size: %u, RAP FLAGS: %d/%d\n",
- n, m, pes_es->payload_size, pl_size, (int) rap_flag, (int) sl->random_accesspoint_only);
-
- return m;
-}
-
-//this function parses the extension fields in the PES header and returns the substream_id, or -1 in case of errors
-static int parse_pes_extension_fields(unsigned char *p, int pkt_len)
-{
- int skip;
- unsigned char flags;
-
- if(!(p[7] & 0x1)) //no extension_field
- return -1;
- skip = 9;
- if(p[7] & 0x80)
- {
- skip += 5;
- if(p[7] & 0x40)
- skip += 5;
- }
- if(p[7] & 0x20) //escr_flag
- skip += 6;
- if(p[7] & 0x10) //es_rate_flag
- skip += 3;
- if(p[7] & 0x08)//dsm_trick_mode is unsupported, skip
- {
- skip = 0;//don't let's parse the extension fields
- }
- if(p[7] & 0x04) //additional_copy_info
- skip += 1;
- if(p[7] & 0x02) //pes_crc_flag
- skip += 2;
- if(skip >= pkt_len) //too few bytes
- return -1;
- flags = p[skip];
- skip++;
- if(flags & 0x80) //pes_private_data_flag
- skip += 16;
- if(skip >= pkt_len)
- return -1;
- if(flags & 0x40) //pack_header_field_flag
- {
- unsigned char l = p[skip];
- skip += l;
- }
- if(flags & 0x20) //program_packet_sequence_counter
- skip += 2;
- if(flags & 0x10) //p_std
- skip += 2;
- if(skip >= pkt_len)
- return -1;
- if(flags & 0x01) //finally the long desired pes_extension2
- {
- unsigned char l = p[skip]; //ext2 flag+len
- skip++;
- if((l == 0x81) && (skip < pkt_len))
- {
- int ssid = p[skip];
- mp_msg(MSGT_IDENTIFY, MSGL_V, "SUBSTREAM_ID=%d (0x%02X)\n", ssid, ssid);
- return ssid;
- }
- }
-
- return -1;
-}
-
-static int pes_parse2(unsigned char *buf, uint16_t packet_len, ES_stream_t *es, int32_t type_from_pmt, pmt_t *pmt, int pid)
-{
- unsigned char *p;
- uint32_t header_len;
- int64_t pts;
- uint32_t stream_id;
- uint32_t pkt_len, pes_is_aligned;
-
- //Here we are always at the start of a PES packet
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2(%p, %d): \n", buf, (uint32_t) packet_len);
-
- if(packet_len == 0 || packet_len > 184)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2, BUFFER LEN IS TOO SMALL OR TOO BIG: %d EXIT\n", packet_len);
- return 0;
- }
-
- p = buf;
- pkt_len = packet_len;
-
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: HEADER %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3]);
- if (p[0] || p[1] || (p[2] != 1))
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: error HEADER %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]);
- return 0 ;
- }
-
- packet_len -= 6;
- if(packet_len==0)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: packet too short: %d, exit\n", packet_len);
- return 0;
- }
-
- es->payload_size = (p[4] << 8 | p[5]);
- pes_is_aligned = (p[6] & 4);
-
- stream_id = p[3];
-
-
- if (p[7] & 0x80)
- { /* pts available */
- pts = (int64_t)(p[9] & 0x0E) << 29 ;
- pts |= p[10] << 22 ;
- pts |= (p[11] & 0xFE) << 14 ;
- pts |= p[12] << 7 ;
- pts |= (p[13] & 0xFE) >> 1 ;
-
- es->pts = pts / 90000.0;
- }
- else
- es->pts = 0.0;
-
-
- header_len = p[8];
-
-
- if (header_len + 9 > pkt_len) //9 are the bytes read up to the header_length field
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "demux_ts: illegal value for PES_header_data_length (0x%02x)\n", header_len);
- return 0;
- }
-
- if(stream_id==0xfd)
- {
- int ssid = parse_pes_extension_fields(p, pkt_len);
- if((audio_substream_id!=-1) && (ssid != audio_substream_id))
- return 0;
- if(ssid == 0x72 && type_from_pmt != AUDIO_DTS && type_from_pmt != SPU_PGS)
- es->type = type_from_pmt = AUDIO_TRUEHD;
- }
-
- p += header_len + 9;
- packet_len -= header_len + 3;
-
- if(es->payload_size)
- es->payload_size -= header_len + 3;
-
-
- es->is_synced = 1; //only for SL streams we have to make sure it's really true, see below
- if (stream_id == 0xbd)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG3, "pes_parse2: audio buf = %02X %02X %02X %02X %02X %02X %02X %02X, 80: %d\n",
- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[0] & 0x80);
-
-
- /*
- * we check the descriptor tag first because some stations
- * do not include any of the A52 header info in their audio tracks
- * these "raw" streams may begin with a byte that looks like a stream type.
- */
-
-
- if(type_from_pmt == SPU_PGS)
- {
- es->start = p;
- es->size = packet_len;
- es->type = SPU_PGS;
- es->payload_size -= packet_len;
- return 1;
- }
- if(
- (type_from_pmt == AUDIO_A52) || /* A52 - raw */
- (packet_len >= 2 && p[0] == 0x0B && p[1] == 0x77) /* A52 - syncword */
- )
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "A52 RAW OR SYNCWORD\n");
- es->start = p;
- es->size = packet_len;
- es->type = AUDIO_A52;
- es->payload_size -= packet_len;
-
- return 1;
- }
- /* SPU SUBS */
- else if(type_from_pmt == SPU_DVB ||
- (packet_len >= 2 && (p[0] == 0x20) && pes_is_aligned)) // && p[1] == 0x00))
- {
- // offset/length fiddling to make decoding with lavc possible
- es->start = p + 2;
- es->size = packet_len - 2;
- es->type = SPU_DVB;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else if (pes_is_aligned && packet_len >= 1 && ((p[0] & 0xE0) == 0x20)) //SPU_DVD
- {
- //DVD SUBS
- es->start = p+1;
- es->size = packet_len-1;
- es->type = SPU_DVD;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else if (pes_is_aligned && packet_len >= 4 && (p[0] & 0xF8) == 0x80)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "A52 WITH HEADER\n");
- es->start = p+4;
- es->size = packet_len - 4;
- es->type = AUDIO_A52;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else if (pes_is_aligned && packet_len >= 1 && ((p[0]&0xf0) == 0xa0))
- {
- int pcm_offset;
-
- for (pcm_offset=0; ++pcm_offset < packet_len-1 ; )
- {
- if (p[pcm_offset] == 0x01 && p[pcm_offset+1] == 0x80)
- { /* START */
- pcm_offset += 2;
- break;
- }
- }
-
- es->start = p + pcm_offset;
- es->size = packet_len - pcm_offset;
- es->type = AUDIO_LPCM_BE;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "PES_PRIVATE1\n");
- es->start = p;
- es->size = packet_len;
- es->type = (type_from_pmt == UNKNOWN ? PES_PRIVATE1 : type_from_pmt);
- es->payload_size -= packet_len;
-
- return 1;
- }
- }
- else if((stream_id >= 0xe0 && stream_id <= 0xef) || (stream_id == 0xfd && type_from_pmt != UNKNOWN))
- {
- es->start = p;
- es->size = packet_len;
- if(type_from_pmt != UNKNOWN)
- es->type = type_from_pmt;
- else
- es->type = VIDEO_MPEG2;
- if(es->payload_size)
- es->payload_size -= packet_len;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: M2V size %d\n", es->size);
- return 1;
- }
- else if (stream_id == 0xfa)
- {
- int l;
-
- es->is_synced = 0;
- if(type_from_pmt != UNKNOWN) //MP4 A/V or SL
- {
- es->start = p;
- es->size = packet_len;
- es->type = type_from_pmt;
-
- if(type_from_pmt == SL_PES_STREAM)
- {
- //if(pes_is_aligned)
- //{
- l = mp4_parse_sl_packet(pmt, p, packet_len, pid, es);
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "L=%d, TYPE=%x\n", l, type_from_pmt);
- if(l < 0)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: couldn't parse SL header, passing along full PES payload\n");
- l = 0;
- }
- //}
-
- es->start += l;
- es->size -= l;
- }
-
- if(es->payload_size)
- es->payload_size -= packet_len;
- return 1;
- }
- }
- else if ((stream_id & 0xe0) == 0xc0)
- {
- es->start = p;
- es->size = packet_len;
-
- if(type_from_pmt != UNKNOWN)
- es->type = type_from_pmt;
- else
- es->type = AUDIO_MP2;
-
- es->payload_size -= packet_len;
-
- return 1;
- }
- else if (type_from_pmt != -1) //as a last resort here we trust the PMT, if present
- {
- es->start = p;
- es->size = packet_len;
- es->type = type_from_pmt;
- es->payload_size -= packet_len;
-
- return 1;
- }
- else
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: unknown packet, id: %x\n", stream_id);
- }
-
- es->is_synced = 0;
- return 0;
-}
-
-
-
-
-static int ts_sync(stream_t *stream)
-{
- mp_msg(MSGT_DEMUX, MSGL_DBG3, "TS_SYNC \n");
-
- while (!stream->eof)
- if (stream_read_char(stream) == 0x47)
- return 1;
-
- return 0;
-}
-
-
-static void ts_dump_streams(ts_priv_t *priv)
-{
- int i;
-
- for(i = 0; i < 3; i++)
- {
- if((priv->fifo[i].pack != NULL) && (priv->fifo[i].offset != 0))
- {
- resize_demux_packet(priv->fifo[i].pack, priv->fifo[i].offset);
- ds_add_packet(priv->fifo[i].ds, priv->fifo[i].pack);
- priv->fifo[i].offset = 0;
- priv->fifo[i].pack = NULL;
- }
- }
-}
-
-
-static inline int32_t prog_idx_in_pat(ts_priv_t *priv, uint16_t progid)
-{
- int x;
-
- if(priv->pat.progs == NULL)
- return -1;
-
- for(x = 0; x < priv->pat.progs_cnt; x++)
- {
- if(priv->pat.progs[x].id == progid)
- return x;
- }
-
- return -1;
-}
-
-
-static inline int32_t prog_id_in_pat(ts_priv_t *priv, uint16_t pid)
-{
- int x;
-
- if(priv->pat.progs == NULL)
- return -1;
-
- for(x = 0; x < priv->pat.progs_cnt; x++)
- {
- if(priv->pat.progs[x].pmt_pid == pid)
- return priv->pat.progs[x].id;
- }
-
- return -1;
-}
-
-static int collect_section(ts_section_t *section, int is_start, unsigned char *buff, int size)
-{
- uint8_t *ptr;
- uint16_t tlen;
- int skip, tid;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "COLLECT_SECTION, start: %d, size: %d, collected: %d\n", is_start, size, section->buffer_len);
- if(! is_start && !section->buffer_len)
- return 0;
-
- if(is_start)
- {
- if(! section->buffer)
- {
- section->buffer = malloc(4096 + 256);
- if(section->buffer == NULL)
- return 0;
- }
- section->buffer_len = 0;
- }
-
- if(size + section->buffer_len > 4096+256)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "COLLECT_SECTION, excessive len: %d + %d\n", section->buffer_len, size);
- return 0;
- }
-
- memcpy(&(section->buffer[section->buffer_len]), buff, size);
- section->buffer_len += size;
-
- if(section->buffer_len < 3)
- return 0;
-
- skip = section->buffer[0];
- if(skip + 4 > section->buffer_len)
- return 0;
-
- ptr = &(section->buffer[skip + 1]);
- tid = ptr[0];
- tlen = ((ptr[1] & 0x0f) << 8) | ptr[2];
- mp_msg(MSGT_DEMUX, MSGL_V, "SKIP: %d+1, TID: %d, TLEN: %d, COLLECTED: %d\n", skip, tid, tlen, section->buffer_len);
- if(section->buffer_len < (skip+1+3+tlen))
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "DATA IS NOT ENOUGH, NEXT TIME\n");
- return 0;
- }
-
- return skip+1;
-}
-
-static int parse_pat(ts_priv_t * priv, int is_start, unsigned char *buff, int size)
-{
- int skip;
- unsigned char *ptr;
- unsigned char *base;
- int entries, i;
- uint16_t progid;
- struct pat_progs_t *tmp;
- ts_section_t *section;
-
- section = &(priv->pat.section);
- skip = collect_section(section, is_start, buff, size);
- if(! skip)
- return 0;
-
- ptr = &(section->buffer[skip]);
- //PARSING
- priv->pat.table_id = ptr[0];
- if(priv->pat.table_id != 0)
- return 0;
- priv->pat.ssi = (ptr[1] >> 7) & 0x1;
- priv->pat.curr_next = ptr[5] & 0x01;
- priv->pat.ts_id = (ptr[3] << 8 ) | ptr[4];
- priv->pat.version_number = (ptr[5] >> 1) & 0x1F;
- priv->pat.section_length = ((ptr[1] & 0x03) << 8 ) | ptr[2];
- priv->pat.section_number = ptr[6];
- priv->pat.last_section_number = ptr[7];
-
- //check_crc32(0xFFFFFFFFL, ptr, priv->pat.buffer_len - 4, &ptr[priv->pat.buffer_len - 4]);
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PAT: section_len: %d, section %d/%d\n", priv->pat.section_length, priv->pat.section_number, priv->pat.last_section_number);
-
- entries = (int) (priv->pat.section_length - 9) / 4; //entries per section
-
- for(i=0; i < entries; i++)
- {
- int32_t idx;
- base = &ptr[8 + i*4];
- progid = (base[0] << 8) | base[1];
-
- if((idx = prog_idx_in_pat(priv, progid)) == -1)
- {
- int sz = sizeof(struct pat_progs_t) * (priv->pat.progs_cnt+1);
- tmp = realloc_struct(priv->pat.progs, priv->pat.progs_cnt+1, sizeof(struct pat_progs_t));
- if(tmp == NULL)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PAT: COULDN'T REALLOC %d bytes, NEXT\n", sz);
- break;
- }
- priv->pat.progs = tmp;
- idx = priv->pat.progs_cnt;
- priv->pat.progs_cnt++;
- }
-
- priv->pat.progs[idx].id = progid;
- priv->pat.progs[idx].pmt_pid = ((base[2] & 0x1F) << 8) | base[3];
- mp_msg(MSGT_DEMUX, MSGL_V, "PROG: %d (%d-th of %d), PMT: %d\n", priv->pat.progs[idx].id, i+1, entries, priv->pat.progs[idx].pmt_pid);
- mp_msg(MSGT_IDENTIFY, MSGL_V, "PROGRAM_ID=%d (0x%02X), PMT_PID: %d(0x%02X)\n",
- progid, progid, priv->pat.progs[idx].pmt_pid, priv->pat.progs[idx].pmt_pid);
- }
-
- return 1;
-}
-
-
-static inline int32_t es_pid_in_pmt(pmt_t * pmt, uint16_t pid)
-{
- uint16_t i;
-
- if(pmt == NULL)
- return -1;
-
- if(pmt->es == NULL)
- return -1;
-
- for(i = 0; i < pmt->es_cnt; i++)
- {
- if(pmt->es[i].pid == pid)
- return (int32_t) i;
- }
-
- return -1;
-}
-
-
-static uint16_t get_mp4_desc_len(uint8_t *buf, int *len)
-{
- //uint16_t i = 0, size = 0;
- int i = 0, j, size = 0;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "PARSE_MP4_DESC_LEN(%d), bytes: ", *len);
- j = FFMIN(*len, 4);
- while(i < j)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, " %x ", buf[i]);
- size |= (buf[i] & 0x7f);
- if(!(buf[i] & 0x80))
- break;
- size <<= 7;
- i++;
- }
- mp_msg(MSGT_DEMUX, MSGL_DBG2, ", SIZE=%d\n", size);
-
- *len = i+1;
- return size;
-}
-
-
-static uint16_t parse_mp4_slconfig_descriptor(uint8_t *buf, int len, void *elem)
-{
- int i = 0;
- mp4_es_descr_t *es;
- mp4_sl_config_t *sl;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_SLCONFIG_DESCRIPTOR(%d)\n", len);
- es = (mp4_es_descr_t *) elem;
- if(!es)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n");
- return len;
- }
- sl = &(es->sl);
-
- sl->ts_len = sl->ocr_len = sl->au_len = sl->instant_bitrate_len = sl->degr_len = sl->au_seqnum_len = sl->packet_seqnum_len = 0;
- sl->ocr = sl->dts = sl->cts = 0;
-
- if(buf[0] == 0)
- {
- i++;
- sl->flags = buf[i];
- i++;
- sl->ts_resolution = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3];
- i += 4;
- sl->ocr_resolution = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3];
- i += 4;
- sl->ts_len = buf[i];
- i++;
- sl->ocr_len = buf[i];
- i++;
- sl->au_len = buf[i];
- i++;
- sl->instant_bitrate_len = buf[i];
- i++;
- sl->degr_len = (buf[i] >> 4) & 0x0f;
- sl->au_seqnum_len = ((buf[i] & 0x0f) << 1) | ((buf[i+1] >> 7) & 0x01);
- i++;
- sl->packet_seqnum_len = ((buf[i] >> 2) & 0x1f);
- i++;
-
- }
- else if(buf[0] == 1)
- {
- sl->flags = 0;
- sl->ts_resolution = 1000;
- sl->ts_len = 32;
- i++;
- }
- else if(buf[0] == 2)
- {
- sl->flags = 4;
- i++;
- }
- else
- {
- sl->flags = 0;
- i++;
- }
-
- sl->au_start = (sl->flags >> 7) & 0x1;
- sl->au_end = (sl->flags >> 6) & 0x1;
- sl->random_accesspoint = (sl->flags >> 5) & 0x1;
- sl->random_accesspoint_only = (sl->flags >> 4) & 0x1;
- sl->padding = (sl->flags >> 3) & 0x1;
- sl->use_ts = (sl->flags >> 2) & 0x1;
- sl->idle = (sl->flags >> 1) & 0x1;
- sl->duration = sl->flags & 0x1;
-
- if(sl->duration)
- {
- sl->timescale = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3];
- i += 4;
- sl->au_duration = (buf[i] << 8) | buf[i+1];
- i += 2;
- sl->cts_duration = (buf[i] << 8) | buf[i+1];
- i += 2;
- }
- else //no support for fixed durations atm
- sl->timescale = sl->au_duration = sl->cts_duration = 0;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "MP4SLCONFIG(len=0x%x), predef: %d, flags: %x, use_ts: %d, tslen: %d, timescale: %d, dts: %"PRIu64", cts: %"PRIu64"\n",
- len, buf[0], sl->flags, sl->use_ts, sl->ts_len, sl->timescale, (uint64_t) sl->dts, (uint64_t) sl->cts);
-
- return len;
-}
-
-static int parse_mp4_descriptors(pmt_t *pmt, uint8_t *buf, int len, void *elem);
-
-static uint16_t parse_mp4_decoder_config_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem)
-{
- int i = 0, j;
- mp4_es_descr_t *es;
- mp4_decoder_config_t *dec;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DECODER_CONFIG_DESCRIPTOR(%d)\n", len);
- es = (mp4_es_descr_t *) elem;
- if(!es)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n");
- return len;
- }
- dec = (mp4_decoder_config_t*) &(es->decoder);
-
- dec->object_type = buf[i];
- dec->stream_type = (buf[i+1]>>2) & 0x3f;
-
- if(dec->object_type == 1 && dec->stream_type == 1)
- {
- dec->object_type = MP4_OD;
- dec->stream_type = MP4_OD;
- }
- else if(dec->stream_type == 4)
- {
- if(dec->object_type == 0x6a)
- dec->object_type = VIDEO_MPEG1;
- if(dec->object_type >= 0x60 && dec->object_type <= 0x65)
- dec->object_type = VIDEO_MPEG2;
- else if(dec->object_type == 0x20)
- dec->object_type = VIDEO_MPEG4;
- else if(dec->object_type == 0x21)
- dec->object_type = VIDEO_AVC;
- /*else if(dec->object_type == 0x22)
- fprintf(stderr, "TYPE 0x22\n");*/
- else dec->object_type = UNKNOWN;
- }
- else if(dec->stream_type == 5)
- {
- if(dec->object_type == 0x40)
- dec->object_type = AUDIO_AAC;
- else if(dec->object_type == 0x6b)
- dec->object_type = AUDIO_MP2;
- else if(dec->object_type >= 0x66 && dec->object_type <= 0x69)
- dec->object_type = AUDIO_MP2;
- else
- dec->object_type = UNKNOWN;
- }
- else
- dec->object_type = dec->stream_type = UNKNOWN;
-
- if(dec->object_type != UNKNOWN)
- {
- //update the type of the current stream
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(pmt->es[j].mp4_es_id == es->id)
- {
- pmt->es[j].type = SL_PES_STREAM;
- }
- }
- }
-
- if(len > 13)
- parse_mp4_descriptors(pmt, &buf[13], len-13, dec);
-
- mp_msg(MSGT_DEMUX, MSGL_V, "MP4DECODER(0x%x), object_type: 0x%x, stream_type: 0x%x\n", len, dec->object_type, dec->stream_type);
-
- return len;
-}
-
-static uint16_t parse_mp4_decoder_specific_descriptor(uint8_t *buf, int len, void *elem)
-{
- int i;
- mp4_decoder_config_t *dec;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DECODER_SPECIFIC_DESCRIPTOR(%d)\n", len);
- dec = (mp4_decoder_config_t *) elem;
- if(!dec)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "argh! NULL elem passed, skip\n");
- return len;
- }
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4 SPECIFIC INFO BYTES: \n");
- for(i=0; i<len; i++)
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "%02x ", buf[i]);
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "\n");
-
- if(len > MAX_EXTRADATA_SIZE)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "DEMUX_TS, EXTRADATA SUSPICIOUSLY BIG: %d, REFUSED\r\n", len);
- return len;
- }
- memcpy(dec->buf, buf, len);
- dec->buf_size = len;
-
- return len;
-}
-
-static uint16_t parse_mp4_es_descriptor(pmt_t *pmt, uint8_t *buf, int len)
-{
- int i = 0, j = 0, k, found;
- uint8_t flag;
- mp4_es_descr_t es, *target_es = NULL, *tmp;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4ES: len=%d\n", len);
- memset(&es, 0, sizeof(mp4_es_descr_t));
- while(i < len)
- {
- es.id = (buf[i] << 8) | buf[i+1];
- mp_msg(MSGT_DEMUX, MSGL_V, "MP4ES_ID: %d\n", es.id);
- i += 2;
- flag = buf[i];
- i++;
- if(flag & 0x80)
- i += 2;
- if(flag & 0x40)
- i += buf[i]+1;
- if(flag & 0x20) //OCR, maybe we need it
- i += 2;
-
- j = parse_mp4_descriptors(pmt, &buf[i], len-i, &es);
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4ES, types after parse_mp4_descriptors: 0x%x, 0x%x\n", es.decoder.object_type, es.decoder.stream_type);
- if(es.decoder.object_type != UNKNOWN && es.decoder.stream_type != UNKNOWN)
- {
- found = 0;
- //search this ES_ID if we already have it
- for(k=0; k < pmt->mp4es_cnt; k++)
- {
- if(pmt->mp4es[k].id == es.id)
- {
- target_es = &(pmt->mp4es[k]);
- found = 1;
- }
- }
-
- if(! found)
- {
- tmp = realloc_struct(pmt->mp4es, pmt->mp4es_cnt+1, sizeof(mp4_es_descr_t));
- if(tmp == NULL)
- {
- fprintf(stderr, "CAN'T REALLOC MP4_ES_DESCR\n");
- continue;
- }
- pmt->mp4es = tmp;
- target_es = &(pmt->mp4es[pmt->mp4es_cnt]);
- pmt->mp4es_cnt++;
- }
- memcpy(target_es, &es, sizeof(mp4_es_descr_t));
- mp_msg(MSGT_DEMUX, MSGL_V, "MP4ES_CNT: %d, ID=%d\n", pmt->mp4es_cnt, target_es->id);
- }
-
- i += j;
- }
-
- return len;
-}
-
-static void parse_mp4_object_descriptor(pmt_t *pmt, uint8_t *buf, int len, void *elem)
-{
- int i, j = 0, id;
-
- i=0;
- id = (buf[0] << 2) | ((buf[1] & 0xc0) >> 6);
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_OBJECT_DESCRIPTOR: len=%d, OD_ID=%d\n", len, id);
- if(buf[1] & 0x20)
- {
- i += buf[2] + 1; //url
- mp_msg(MSGT_DEMUX, MSGL_V, "URL\n");
- }
- else
- {
- i = 2;
-
- while(i < len)
- {
- j = parse_mp4_descriptors(pmt, &(buf[i]), len-i, elem);
- mp_msg(MSGT_DEMUX, MSGL_V, "OBJD, NOW i = %d, j=%d, LEN=%d\n", i, j, len);
- i += j;
- }
- }
-}
-
-
-static void parse_mp4_iod(pmt_t *pmt, uint8_t *buf, int len, void *elem)
-{
- int i, j = 0;
- mp4_od_t *iod = &(pmt->iod);
-
- iod->id = (buf[0] << 2) | ((buf[1] & 0xc0) >> 6);
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_IOD: len=%d, IOD_ID=%d\n", len, iod->id);
- i = 2;
- if(buf[1] & 0x20)
- {
- i += buf[2] + 1; //url
- mp_msg(MSGT_DEMUX, MSGL_V, "URL\n");
- }
- else
- {
- i = 7;
- while(i < len)
- {
- j = parse_mp4_descriptors(pmt, &(buf[i]), len-i, elem);
- mp_msg(MSGT_DEMUX, MSGL_V, "IOD, NOW i = %d, j=%d, LEN=%d\n", i, j, len);
- i += j;
- }
- }
-}
-
-static int parse_mp4_descriptors(pmt_t *pmt, uint8_t *buf, int len, void *elem)
-{
- int tag, descr_len, i = 0, j = 0;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_MP4_DESCRIPTORS, len=%d\n", len);
- if(! len)
- return len;
-
- while(i < len)
- {
- tag = buf[i];
- j = len - i -1;
- descr_len = get_mp4_desc_len(&(buf[i+1]), &j);
- mp_msg(MSGT_DEMUX, MSGL_V, "TAG=%d (0x%x), DESCR_len=%d, len=%d, j=%d\n", tag, tag, descr_len, len, j);
- if(descr_len > len - j+1)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "descriptor is too long, exit\n");
- return len;
- }
- i += j+1;
-
- switch(tag)
- {
- case 0x1:
- parse_mp4_object_descriptor(pmt, &(buf[i]), descr_len, elem);
- break;
- case 0x2:
- parse_mp4_iod(pmt, &(buf[i]), descr_len, elem);
- break;
- case 0x3:
- parse_mp4_es_descriptor(pmt, &(buf[i]), descr_len);
- break;
- case 0x4:
- parse_mp4_decoder_config_descriptor(pmt, &buf[i], descr_len, elem);
- break;
- case 0x05:
- parse_mp4_decoder_specific_descriptor(&buf[i], descr_len, elem);
- break;
- case 0x6:
- parse_mp4_slconfig_descriptor(&buf[i], descr_len, elem);
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_V, "Unsupported mp4 descriptor 0x%x\n", tag);
- }
- i += descr_len;
- }
-
- return len;
-}
-
-static ES_stream_t *new_pid(ts_priv_t *priv, int pid)
-{
- ES_stream_t *tss;
-
- tss = calloc(sizeof(*tss), 1);
- if(! tss)
- return NULL;
- tss->pid = pid;
- tss->last_cc = -1;
- tss->type = UNKNOWN;
- tss->subtype = UNKNOWN;
- tss->is_synced = 0;
- tss->extradata = NULL;
- tss->extradata_alloc = tss->extradata_len = 0;
- priv->ts.pids[pid] = tss;
-
- return tss;
-}
-
-
-static int parse_program_descriptors(pmt_t *pmt, uint8_t *buf, uint16_t len)
-{
- uint16_t i = 0, k, olen = len;
-
- while(len > 0)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "PROG DESCR, TAG=%x, LEN=%d(%x)\n", buf[i], buf[i+1], buf[i+1]);
- if(buf[i+1] > len-2)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "ERROR, descriptor len is too long, skipping\n");
- return olen;
- }
-
- if(buf[i] == 0x1d)
- {
- if(buf[i+3] == 2) //buggy versions of vlc muxer make this non-standard mess (missing iod_scope)
- k = 3;
- else
- k = 4; //this is standard compliant
- parse_mp4_descriptors(pmt, &buf[i+k], (int) buf[i+1]-(k-2), NULL);
- }
-
- len -= 2 + buf[i+1];
- }
-
- return olen;
-}
-
-static int parse_descriptors(struct pmt_es_t *es, uint8_t *ptr)
-{
- int j, descr_len, len;
-
- j = 0;
- len = es->descr_length;
- while(len > 2)
- {
- descr_len = ptr[j+1];
- mp_msg(MSGT_DEMUX, MSGL_V, "...descr id: 0x%x, len=%d\n", ptr[j], descr_len);
- if(descr_len > len)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "INVALID DESCR LEN for tag %02x: %d vs %d max, EXIT LOOP\n", ptr[j], descr_len, len);
- return -1;
- }
-
-
- if(ptr[j] == 0x6a || ptr[j] == 0x7a) //A52 Descriptor
- {
- if(es->type == 0x6)
- {
- es->type = AUDIO_A52;
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "DVB A52 Descriptor\n");
- }
- }
- else if(ptr[j] == 0x7b) //DVB DTS Descriptor
- {
- if(es->type == 0x6)
- {
- es->type = AUDIO_DTS;
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "DVB DTS Descriptor\n");
- }
- }
- else if(ptr[j] == 0x56) // Teletext
- {
- if(descr_len >= 5) {
- memcpy(es->lang, ptr+2, 3);
- es->lang[3] = 0;
- }
- es->type = SPU_TELETEXT;
- }
- else if(ptr[j] == 0x59) //Subtitling Descriptor
- {
- uint8_t subtype;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Subtitling Descriptor\n");
- if(descr_len < 8)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Descriptor length too short for DVB Subtitle Descriptor: %d, SKIPPING\n", descr_len);
- }
- else
- {
- memcpy(es->lang, &ptr[j+2], 3);
- es->lang[3] = 0;
- subtype = ptr[j+5];
- if(
- (subtype >= 0x10 && subtype <= 0x13) ||
- (subtype >= 0x20 && subtype <= 0x23)
- )
- {
- es->type = SPU_DVB;
- //page parameters: compo page 2 bytes, ancillary page 2 bytes
- }
- else
- es->type = UNKNOWN;
- }
- }
- else if(ptr[j] == 0x50) //Component Descriptor
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Component Descriptor\n");
- memcpy(es->lang, &ptr[j+5], 3);
- es->lang[3] = 0;
- }
- else if(ptr[j] == 0xa) //Language Descriptor
- {
- memcpy(es->lang, &ptr[j+2], 3);
- es->lang[3] = 0;
- mp_msg(MSGT_DEMUX, MSGL_V, "Language Descriptor: %s\n", es->lang);
- }
- else if(ptr[j] == 0x5) //Registration Descriptor (looks like e fourCC :) )
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Registration Descriptor\n");
- if(descr_len < 4)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Registration Descriptor length too short: %d, SKIPPING\n", descr_len);
- }
- else
- {
- char *d;
- memcpy(es->format_descriptor, &ptr[j+2], 4);
- es->format_descriptor[4] = 0;
-
- d = &ptr[j+2];
- if(d[0] == 'A' && d[1] == 'C' && d[2] == '-' && d[3] == '3')
- {
- es->type = AUDIO_A52;
- }
- else if(d[0] == 'D' && d[1] == 'T' && d[2] == 'S' && d[3] == '1')
- {
- es->type = AUDIO_DTS;
- }
- else if(d[0] == 'D' && d[1] == 'T' && d[2] == 'S' && d[3] == '2')
- {
- es->type = AUDIO_DTS;
- }
- else if(d[0] == 'V' && d[1] == 'C' && d[2] == '-' && d[3] == '1')
- {
- es->type = VIDEO_VC1;
- }
- else if(d[0] == 'd' && d[1] == 'r' && d[2] == 'a' && d[3] == 'c')
- {
- es->type = VIDEO_DIRAC;
- }
- else if(d[0] == 'B' && d[1] == 'S' && d[2] == 'S' && d[3] == 'D')
- {
- es->type = AUDIO_S302M;
- }
- else
- es->type = UNKNOWN;
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "FORMAT %s\n", es->format_descriptor);
- }
- }
- else if(ptr[j] == 0x1e || ptr[j] == 0x1f)
- {
- // 0x1f is FMC, but currently it is easiest to handle them the same way
- es->mp4_es_id = (ptr[j+2] << 8) | ptr[j+3];
- mp_msg(MSGT_DEMUX, MSGL_V, "SL Descriptor: ES_ID: %d(%x), pid: %d\n", es->mp4_es_id, es->mp4_es_id, es->pid);
- }
- else
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "Unknown descriptor 0x%x, SKIPPING\n", ptr[j]);
-
- len -= 2 + descr_len;
- j += 2 + descr_len;
- }
-
- return 1;
-}
-
-static int parse_sl_section(pmt_t *pmt, ts_section_t *section, int is_start, unsigned char *buff, int size)
-{
- int tid, len, skip;
- uint8_t *ptr;
- skip = collect_section(section, is_start, buff, size);
- if(! skip)
- return 0;
-
- ptr = &(section->buffer[skip]);
- tid = ptr[0];
- len = ((ptr[1] & 0x0f) << 8) | ptr[2];
- mp_msg(MSGT_DEMUX, MSGL_V, "TABLEID: %d (av. %d), skip=%d, LEN: %d\n", tid, section->buffer_len, skip, len);
- if(len > 4093 || section->buffer_len < len || tid != 5)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "SECTION TOO LARGE or wrong section type, EXIT\n");
- return 0;
- }
-
- if(! (ptr[5] & 1))
- return 0;
-
- //8 is the current position, len - 9 is the amount of data available
- parse_mp4_descriptors(pmt, &ptr[8], len - 9, NULL);
-
- return 1;
-}
-
-static int parse_pmt(ts_priv_t * priv, uint16_t progid, uint16_t pid, int is_start, unsigned char *buff, int size)
-{
- unsigned char *base, *es_base;
- pmt_t *pmt;
- int32_t idx, es_count, section_bytes;
- uint8_t m=0;
- int skip;
- pmt_t *tmp;
- struct pmt_es_t *tmp_es;
- ts_section_t *section;
- ES_stream_t *tss;
- int i;
-
- idx = progid_idx_in_pmt(priv, progid);
-
- if(idx == -1)
- {
- int sz = (priv->pmt_cnt + 1) * sizeof(pmt_t);
- tmp = realloc_struct(priv->pmt, priv->pmt_cnt + 1, sizeof(pmt_t));
- if(tmp == NULL)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT: COULDN'T REALLOC %d bytes, NEXT\n", sz);
- return 0;
- }
- priv->pmt = tmp;
- idx = priv->pmt_cnt;
- memset(&(priv->pmt[idx]), 0, sizeof(pmt_t));
- priv->pmt_cnt++;
- priv->pmt[idx].progid = progid;
- }
-
- pmt = &(priv->pmt[idx]);
-
- section = &(pmt->section);
- skip = collect_section(section, is_start, buff, size);
- if(! skip)
- return 0;
-
- base = &(section->buffer[skip]);
-
- mp_msg(MSGT_DEMUX, MSGL_V, "FILL_PMT(prog=%d), PMT_len: %d, IS_START: %d, TS_PID: %d, SIZE=%d, M=%d, ES_CNT=%d, IDX=%d, PMT_PTR=%p\n",
- progid, pmt->section.buffer_len, is_start, pid, size, m, pmt->es_cnt, idx, pmt);
-
- pmt->table_id = base[0];
- if(pmt->table_id != 2)
- return -1;
- pmt->ssi = base[1] & 0x80;
- pmt->section_length = (((base[1] & 0xf) << 8 ) | base[2]);
- pmt->version_number = (base[5] >> 1) & 0x1f;
- pmt->curr_next = (base[5] & 1);
- pmt->section_number = base[6];
- pmt->last_section_number = base[7];
- pmt->PCR_PID = ((base[8] & 0x1f) << 8 ) | base[9];
- pmt->prog_descr_length = ((base[10] & 0xf) << 8 ) | base[11];
- if(pmt->prog_descr_length > pmt->section_length - 9)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, INVALID PROG_DESCR LENGTH (%d vs %d)\n", pmt->prog_descr_length, pmt->section_length - 9);
- return -1;
- }
-
- if(pmt->prog_descr_length)
- parse_program_descriptors(pmt, &base[12], pmt->prog_descr_length);
-
- es_base = &base[12 + pmt->prog_descr_length]; //the beginning of th ES loop
-
- section_bytes= pmt->section_length - 13 - pmt->prog_descr_length;
- es_count = 0;
-
- while(section_bytes >= 5)
- {
- int es_pid, es_type;
-
- es_type = es_base[0];
- es_pid = ((es_base[1] & 0x1f) << 8) | es_base[2];
-
- idx = es_pid_in_pmt(pmt, es_pid);
- if(idx == -1)
- {
- int sz = sizeof(struct pmt_es_t) * (pmt->es_cnt + 1);
- tmp_es = realloc_struct(pmt->es, pmt->es_cnt + 1, sizeof(struct pmt_es_t));
- if(tmp_es == NULL)
- {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT, COULDN'T ALLOCATE %d bytes for PMT_ES\n", sz);
- continue;
- }
- pmt->es = tmp_es;
- idx = pmt->es_cnt;
- memset(&(pmt->es[idx]), 0, sizeof(struct pmt_es_t));
- pmt->es_cnt++;
- }
-
- pmt->es[idx].descr_length = ((es_base[3] & 0xf) << 8) | es_base[4];
-
-
- if(pmt->es[idx].descr_length > section_bytes - 5)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, ES_DESCR_LENGTH TOO LARGE %d > %d, EXIT\n",
- pmt->es[idx].descr_length, section_bytes - 5);
- return -1;
- }
-
-
- pmt->es[idx].pid = es_pid;
- if(es_type != 0x6)
- pmt->es[idx].type = UNKNOWN;
- else
- pmt->es[idx].type = es_type;
-
- parse_descriptors(&pmt->es[idx], &es_base[5]);
-
- switch(es_type)
- {
- case 1:
- pmt->es[idx].type = VIDEO_MPEG1;
- break;
- case 2:
- pmt->es[idx].type = VIDEO_MPEG2;
- break;
- case 3:
- case 4:
- pmt->es[idx].type = AUDIO_MP2;
- break;
- case 6:
- if(pmt->es[idx].type == 0x6) //this could have been ovrwritten by parse_descriptors
- pmt->es[idx].type = UNKNOWN;
- break;
- case 0x10:
- pmt->es[idx].type = VIDEO_MPEG4;
- break;
- case 0x0f:
- pmt->es[idx].type = AUDIO_AAC;
- break;
- case 0x11:
- pmt->es[idx].type = AUDIO_AAC_LATM;
- for (i = 0; i < pmt->mp4es_cnt; i++)
- if (pmt->mp4es[i].id == pmt->es[idx].mp4_es_id &&
- pmt->mp4es[i].decoder.object_type == AUDIO_AAC)
- pmt->es[idx].type = AUDIO_AAC;
- break;
- case 0x1b:
- pmt->es[idx].type = VIDEO_H264;
- break;
- case 0x12:
- pmt->es[idx].type = SL_PES_STREAM;
- break;
- case 0x13:
- pmt->es[idx].type = SL_SECTION;
- break;
- case 0x81:
- pmt->es[idx].type = AUDIO_A52;
- break;
- case 0x8A:
- case 0x82:
- case 0x85:
- case 0x86:
- pmt->es[idx].type = AUDIO_DTS;
- break;
- case 0x90:
- pmt->es[idx].type = SPU_PGS;
- break;
- case 0xD1:
- pmt->es[idx].type = VIDEO_DIRAC;
- break;
- case 0xEA:
- pmt->es[idx].type = VIDEO_VC1;
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "UNKNOWN ES TYPE=0x%x\n", es_type);
- pmt->es[idx].type = UNKNOWN;
- }
-
- tss = priv->ts.pids[es_pid]; //an ES stream
- if(tss == NULL)
- {
- tss = new_pid(priv, es_pid);
- if(tss)
- tss->type = pmt->es[idx].type;
- }
-
- section_bytes -= 5 + pmt->es[idx].descr_length;
- mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT(%d INDEX %d), STREAM: %d, FOUND pid=0x%x (%d), type=0x%x, ES_DESCR_LENGTH: %d, bytes left: %d\n",
- progid, idx, es_count, pmt->es[idx].pid, pmt->es[idx].pid, pmt->es[idx].type, pmt->es[idx].descr_length, section_bytes);
-
-
- es_base += 5 + pmt->es[idx].descr_length;
-
- es_count++;
- }
-
- mp_msg(MSGT_DEMUX, MSGL_V, "----------------------------\n");
- return 1;
-}
-
-static pmt_t* pmt_of_pid(ts_priv_t *priv, int pid, mp4_decoder_config_t **mp4_dec)
-{
- int32_t i, j, k;
-
- if(priv->pmt)
- {
- for(i = 0; i < priv->pmt_cnt; i++)
- {
- if(priv->pmt[i].es && priv->pmt[i].es_cnt)
- {
- for(j = 0; j < priv->pmt[i].es_cnt; j++)
- {
- if(priv->pmt[i].es[j].pid == pid)
- {
- //search mp4_es_id
- if(priv->pmt[i].es[j].mp4_es_id)
- {
- for(k = 0; k < priv->pmt[i].mp4es_cnt; k++)
- {
- if(priv->pmt[i].mp4es[k].id == priv->pmt[i].es[j].mp4_es_id)
- {
- *mp4_dec = &(priv->pmt[i].mp4es[k].decoder);
- break;
- }
- }
- }
-
- return &(priv->pmt[i]);
- }
- }
- }
- }
- }
-
- return NULL;
-}
-
-
-static inline int32_t pid_type_from_pmt(ts_priv_t *priv, int pid)
-{
- int32_t pmt_idx, pid_idx, i, j;
-
- pmt_idx = progid_idx_in_pmt(priv, priv->prog);
-
- if(pmt_idx != -1)
- {
- pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid);
- if(pid_idx != -1)
- return priv->pmt[pmt_idx].es[pid_idx].type;
- }
- //else
- //{
- for(i = 0; i < priv->pmt_cnt; i++)
- {
- pmt_t *pmt = &(priv->pmt[i]);
- for(j = 0; j < pmt->es_cnt; j++)
- if(pmt->es[j].pid == pid)
- return pmt->es[j].type;
- }
- //}
-
- return UNKNOWN;
-}
-
-
-static inline uint8_t *pid_lang_from_pmt(ts_priv_t *priv, int pid)
-{
- int32_t pmt_idx, pid_idx, i, j;
-
- pmt_idx = progid_idx_in_pmt(priv, priv->prog);
-
- if(pmt_idx != -1)
- {
- pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid);
- if(pid_idx != -1)
- return priv->pmt[pmt_idx].es[pid_idx].lang;
- }
- else
- {
- for(i = 0; i < priv->pmt_cnt; i++)
- {
- pmt_t *pmt = &(priv->pmt[i]);
- for(j = 0; j < pmt->es_cnt; j++)
- if(pmt->es[j].pid == pid)
- return pmt->es[j].lang;
- }
- }
-
- return NULL;
-}
-
-
-static int fill_packet(demuxer_t *demuxer, demux_stream_t *ds, demux_packet_t **dp, int *dp_offset, TS_stream_info *si)
-{
- int ret = 0;
-
- if(*dp && *dp_offset <= 0)
- {
- free_demux_packet(*dp);
- *dp = NULL;
- }
- if(*dp)
- {
- ret = *dp_offset;
- resize_demux_packet(*dp, ret); //shrinked to the right size
- ds_add_packet(ds, *dp);
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "ADDED %d bytes to %s fifo, PTS=%.3f\n", ret, (ds == demuxer->audio ? "audio" : (ds == demuxer->video ? "video" : "sub")), (*dp)->pts);
- if(si)
- {
- float diff = (*dp)->pts - si->last_pts;
- float dur;
-
- if(abs(diff) > 1) //1 second, there's a discontinuity
- {
- si->duration += si->last_pts - si->first_pts;
- si->first_pts = si->last_pts = (*dp)->pts;
- }
- else
- {
- si->last_pts = (*dp)->pts;
- }
- si->size += ret;
- dur = si->duration + (si->last_pts - si->first_pts);
-
- if(dur > 0 && ds == demuxer->video)
- {
- ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
- if(dur > 1) //otherwise it may be unreliable
- priv->vbitrate = (uint32_t) ((float) si->size / dur);
- }
- }
- }
-
- *dp = NULL;
- *dp_offset = 0;
-
- return ret;
-}
-
-static int fill_extradata(mp4_decoder_config_t * mp4_dec, ES_stream_t *tss)
-{
- uint8_t *tmp;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4_dec: %p, pid: %d\n", mp4_dec, tss->pid);
-
- if(mp4_dec->buf_size > tss->extradata_alloc)
- {
- tmp = realloc(tss->extradata, mp4_dec->buf_size);
- if(!tmp)
- return 0;
- tss->extradata = tmp;
- tss->extradata_alloc = mp4_dec->buf_size;
- }
- memcpy(tss->extradata, mp4_dec->buf, mp4_dec->buf_size);
- tss->extradata_len = mp4_dec->buf_size;
- mp_msg(MSGT_DEMUX, MSGL_V, "EXTRADATA: %p, alloc=%d, len=%d\n", tss->extradata, tss->extradata_alloc, tss->extradata_len);
-
- return tss->extradata_len;
-}
-
-// 0 = EOF or no stream found
-// else = [-] number of bytes written to the packet
-static int ts_parse(demuxer_t *demuxer , ES_stream_t *es, unsigned char *packet, int probe)
-{
- ES_stream_t *tss;
- int buf_size, is_start, pid, base;
- int len, cc, cc_ok av_unused, afc, retv = 0, is_video, is_audio, is_sub;
- ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
- stream_t *stream = demuxer->stream;
- char *p;
- demux_stream_t *ds = NULL;
- demux_packet_t **dp = NULL;
- int *dp_offset = 0, *buffer_size = 0;
- int32_t progid, pid_type, bad, ts_error;
- int junk = 0, rap_flag = 0;
- pmt_t *pmt;
- mp4_decoder_config_t *mp4_dec;
- TS_stream_info *si;
-
-
- memset(es, 0, sizeof(*es));
- while(1)
- {
- bad = ts_error = 0;
- ds = NULL;
- dp = NULL;
- dp_offset = buffer_size = NULL;
- rap_flag = 0;
- mp4_dec = NULL;
- es->is_synced = 0;
- es->lang[0] = 0;
- si = NULL;
-
- junk = priv->ts.packet_size - TS_PACKET_SIZE;
- buf_size = priv->ts.packet_size - junk;
-
- if(stream_eof(stream))
- {
- if(! probe)
- {
- ts_dump_streams(priv);
- demuxer->filepos = stream_tell(demuxer->stream);
- }
-
- return 0;
- }
-
-
- if(! ts_sync(stream))
- {
- mp_msg(MSGT_DEMUX, MSGL_INFO, "TS_PARSE: COULDN'T SYNC\n");
- return 0;
- }
-
- len = stream_read(stream, &packet[1], 3);
- if (len != 3)
- return 0;
- buf_size -= 4;
-
- if((packet[1] >> 7) & 0x01) //transport error
- ts_error = 1;
-
-
- is_start = packet[1] & 0x40;
- pid = ((packet[1] & 0x1f) << 8) | packet[2];
-
- tss = priv->ts.pids[pid]; //an ES stream
- if(tss == NULL)
- {
- tss = new_pid(priv, pid);
- if(tss == NULL)
- continue;
- }
-
- cc = (packet[3] & 0xf);
- cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc));
- tss->last_cc = cc;
-
- bad = ts_error; // || (! cc_ok);
- if(bad)
- {
- if(priv->keep_broken == 0)
- {
- stream_skip(stream, buf_size-1+junk);
- continue;
- }
-
- is_start = 0; //queued to the packet data
- }
-
- if(is_start)
- tss->is_synced = 1;
-
- if((!is_start && !tss->is_synced) || ((pid > 1) && (pid < 16)) || (pid == 8191)) //invalid pid
- {
- stream_skip(stream, buf_size-1+junk);
- continue;
- }
-
-
- afc = (packet[3] >> 4) & 3;
- if(! (afc % 2)) //no payload in this TS packet
- {
- stream_skip(stream, buf_size-1+junk);
- continue;
- }
-
- if(afc > 1)
- {
- int c;
- c = stream_read_char(stream);
- buf_size--;
- if(c < 0 || c > 183) //broken from the stream layer or invalid
- {
- stream_skip(stream, buf_size-1+junk);
- continue;
- }
-
- //c==0 is allowed!
- if(c > 0)
- {
- uint8_t pcrbuf[188];
- int flags = stream_read_char(stream);
- int has_pcr;
- rap_flag = (flags & 0x40) >> 6;
- has_pcr = flags & 0x10;
-
- buf_size--;
- c--;
- stream_read(stream, pcrbuf, c);
-
- if(has_pcr)
- {
- int pcr_pid = prog_pcr_pid(priv, priv->prog);
- if(pcr_pid == pid)
- {
- uint64_t pcr, pcr_ext;
-
- pcr = (int64_t)(pcrbuf[0]) << 25;
- pcr |= pcrbuf[1] << 17 ;
- pcr |= (pcrbuf[2]) << 9;
- pcr |= pcrbuf[3] << 1 ;
- pcr |= (pcrbuf[4] & 0x80) >> 7;
-
- pcr_ext = (pcrbuf[4] & 0x01) << 8;
- pcr_ext |= pcrbuf[5];
-
- pcr = pcr * 300 + pcr_ext;
-
- demuxer->reference_clock = (double)pcr/(double)27000000.0;
- }
- }
-
- buf_size -= c;
- if(buf_size == 0)
- continue;
- }
- }
-
- //find the program that the pid belongs to; if (it's the right one or -1) && pid_type==SL_SECTION
- //call parse_sl_section()
- pmt = pmt_of_pid(priv, pid, &mp4_dec);
- if(mp4_dec)
- {
- fill_extradata(mp4_dec, tss);
- if(IS_VIDEO(mp4_dec->object_type) || IS_AUDIO(mp4_dec->object_type))
- {
- tss->type = SL_PES_STREAM;
- tss->subtype = mp4_dec->object_type;
- }
- }
-
-
- //TABLE PARSING
-
- base = priv->ts.packet_size - buf_size;
-
- priv->last_pid = pid;
-
- is_video = IS_VIDEO(tss->type) || (tss->type==SL_PES_STREAM && IS_VIDEO(tss->subtype));
- is_audio = IS_AUDIO(tss->type) || (tss->type==SL_PES_STREAM && IS_AUDIO(tss->subtype)) || (tss->type == PES_PRIVATE1);
- is_sub = IS_SUB(tss->type);
- pid_type = pid_type_from_pmt(priv, pid);
-
- // PES CONTENT STARTS HERE
- if(! probe)
- {
- if((is_video || is_audio || is_sub) && is_start)
- ts_add_stream(demuxer, tss);
-
- if(is_video && (demuxer->video->id == priv->ts.streams[pid].id))
- {
- ds = demuxer->video;
-
- dp = &priv->fifo[1].pack;
- dp_offset = &priv->fifo[1].offset;
- buffer_size = &priv->fifo[1].buffer_size;
- si = &priv->vstr;
- }
- else if(is_audio && (demuxer->audio->id == priv->ts.streams[pid].id))
- {
- ds = demuxer->audio;
-
- dp = &priv->fifo[0].pack;
- dp_offset = &priv->fifo[0].offset;
- buffer_size = &priv->fifo[0].buffer_size;
- si = &priv->astr;
- }
- else if(is_sub)
- {
- sh_sub_t *sh_sub = demuxer->sub->sh;
-
- if(sh_sub && sh_sub->sid == tss->pid)
- {
- ds = demuxer->sub;
-
- dp = &priv->fifo[2].pack;
- dp_offset = &priv->fifo[2].offset;
- buffer_size = &priv->fifo[2].buffer_size;
- }
- else
- {
- stream_skip(stream, buf_size+junk);
- continue;
- }
- }
-
- //IS IT TIME TO QUEUE DATA to the dp_packet?
- if(is_start && (dp != NULL))
- {
- retv = fill_packet(demuxer, ds, dp, dp_offset, si);
- }
-
-
- if(dp && *dp == NULL)
- {
- if(*buffer_size > MAX_PACK_BYTES)
- *buffer_size = MAX_PACK_BYTES;
- *dp = new_demux_packet(*buffer_size); //es->size
- *dp_offset = 0;
- if(! *dp)
- {
- fprintf(stderr, "fill_buffer, NEW_ADD_PACKET(%d)FAILED\n", *buffer_size);
- continue;
- }
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "CREATED DP(%d)\n", *buffer_size);
- }
- }
-
-
- if(probe || !dp) //dp is NULL for tables and sections
- {
- p = &packet[base];
- }
- else //feeding
- {
- if(*dp_offset + buf_size > *buffer_size)
- {
- *buffer_size = *dp_offset + buf_size + TS_FEC_PACKET_SIZE;
- resize_demux_packet(*dp, *buffer_size);
- }
- p = &((*dp)->buffer[*dp_offset]);
- }
-
- len = stream_read(stream, p, buf_size);
- if(len < buf_size)
- {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "\r\nts_parse() couldn't read enough data: %d < %d\r\n", len, buf_size);
- continue;
- }
- stream_skip(stream, junk);
-
- if(pid == 0)
- {
- parse_pat(priv, is_start, p, buf_size);
- continue;
- }
- else if((tss->type == SL_SECTION) && pmt)
- {
- int k, mp4_es_id = -1;
- ts_section_t *section;
- for(k = 0; k < pmt->mp4es_cnt; k++)
- {
- if(pmt->mp4es[k].decoder.object_type == MP4_OD && pmt->mp4es[k].decoder.stream_type == MP4_OD)
- mp4_es_id = pmt->mp4es[k].id;
- }
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4ESID: %d\n", mp4_es_id);
- for(k = 0; k < pmt->es_cnt; k++)
- {
- if(pmt->es[k].mp4_es_id == mp4_es_id)
- {
- section = &(tss->section);
- parse_sl_section(pmt, section, is_start, &packet[base], buf_size);
- }
- }
- continue;
- }
- else
- {
- progid = prog_id_in_pat(priv, pid);
- if(progid != -1)
- {
- if(pid != demuxer->video->id && pid != demuxer->audio->id && pid != demuxer->sub->id)
- {
- parse_pmt(priv, progid, pid, is_start, &packet[base], buf_size);
- continue;
- }
- else
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Argh! Data pid %d used in the PMT, Skipping PMT parsing!\n", pid);
- }
- }
-
- if(!probe && !dp)
- continue;
-
- if(is_start)
- {
- uint8_t *lang = NULL;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "IS_START\n");
-
- len = pes_parse2(p, buf_size, es, pid_type, pmt, pid);
- if(! len)
- {
- tss->is_synced = 0;
- continue;
- }
- es->pid = tss->pid;
- tss->is_synced |= es->is_synced || rap_flag;
- tss->payload_size = es->payload_size;
-
- if((is_sub || is_audio) && (lang = pid_lang_from_pmt(priv, es->pid)))
- {
- memcpy(es->lang, lang, 3);
- es->lang[3] = 0;
- }
- else
- es->lang[0] = 0;
-
- if(probe)
- {
- if(es->type == UNKNOWN)
- return 0;
-
- tss->type = es->type;
- tss->subtype = es->subtype;
-
- return 1;
- }
- else
- {
- if(es->pts == 0.0)
- es->pts = tss->pts = tss->last_pts;
- else
- tss->pts = tss->last_pts = es->pts;
-
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "ts_parse, NEW pid=%d, PSIZE: %u, type=%X, start=%p, len=%d\n",
- es->pid, es->payload_size, es->type, es->start, es->size);
-
- demuxer->filepos = stream_tell(demuxer->stream) - es->size;
-
- if(es->size < 0 || es->size > buf_size) {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "Broken ES packet size\n");
- es->size = 0;
- }
- memmove(p, es->start, es->size);
- *dp_offset += es->size;
- (*dp)->keyframe = 0;
- (*dp)->pos = stream_tell(demuxer->stream);
- (*dp)->pts = es->pts;
- // subtitle packets must be returned immediately if possible
- if (is_sub && !tss->payload_size)
- retv = fill_packet(demuxer, ds, dp, dp_offset, si);
-
- if(retv > 0)
- return retv;
- else
- continue;
- }
- }
- else
- {
- uint16_t sz;
-
- es->pid = tss->pid;
- es->type = tss->type;
- es->subtype = tss->subtype;
- es->pts = tss->pts = tss->last_pts;
- es->start = &packet[base];
-
-
- if(tss->payload_size > 0)
- {
- sz = FFMIN(tss->payload_size, buf_size);
- tss->payload_size -= sz;
- es->size = sz;
- }
- else
- {
- if(is_video)
- {
- sz = es->size = buf_size;
- }
- else
- {
- continue;
- }
- }
-
-
- if(! probe)
- {
- *dp_offset += sz;
-
- // subtitle packets must be returned immediately if possible
- if(*dp_offset >= MAX_PACK_BYTES || (is_sub && !tss->payload_size))
- {
- (*dp)->pts = tss->last_pts;
- retv = fill_packet(demuxer, ds, dp, dp_offset, si);
- return 1;
- }
-
- continue;
- }
- else
- {
- memmove(es->start, p, sz);
-
- if(es->size)
- return es->size;
- else
- continue;
- }
- }
- }
-
- return 0;
-}
-
-
-static void reset_fifos(demuxer_t *demuxer, int a, int v, int s)
-{
- ts_priv_t* priv = demuxer->priv;
- if(a)
- {
- if(priv->fifo[0].pack != NULL)
- {
- free_demux_packet(priv->fifo[0].pack);
- priv->fifo[0].pack = NULL;
- }
- priv->fifo[0].offset = 0;
- }
-
- if(v)
- {
- if(priv->fifo[1].pack != NULL)
- {
- free_demux_packet(priv->fifo[1].pack);
- priv->fifo[1].pack = NULL;
- }
- priv->fifo[1].offset = 0;
- }
-
- if(s)
- {
- if(priv->fifo[2].pack != NULL)
- {
- free_demux_packet(priv->fifo[2].pack);
- priv->fifo[2].pack = NULL;
- }
- priv->fifo[2].offset = 0;
- }
- demuxer->reference_clock = MP_NOPTS_VALUE;
-}
-
-
-static void demux_seek_ts(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags)
-{
- demux_stream_t *d_audio=demuxer->audio;
- demux_stream_t *d_video=demuxer->video;
- sh_audio_t *sh_audio=d_audio->sh;
- sh_video_t *sh_video=d_video->sh;
- ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
- int i, video_stats;
- off_t newpos;
-
- //================= seek in MPEG-TS ==========================
-
- ts_dump_streams(demuxer->priv);
- reset_fifos(demuxer, sh_audio != NULL, sh_video != NULL, demuxer->sub->id > 0);
-
- demux_flush(demuxer);
-
-
-
- video_stats = (sh_video != NULL);
- if(video_stats)
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "IBPS: %d, vb: %d\r\n", sh_video->i_bps, priv->vbitrate);
- if(priv->vbitrate)
- video_stats = priv->vbitrate;
- else
- video_stats = sh_video->i_bps;
- }
-
- newpos = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : demuxer->filepos;
- if(flags & SEEK_FACTOR) // float seek 0..1
- newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs;
- else
- {
- // time seek (secs)
- if(! video_stats) // unspecified or VBR
- newpos += 2324*75*rel_seek_secs; // 174.3 kbyte/sec
- else
- newpos += video_stats*rel_seek_secs;
- }
-
-
- if(newpos < demuxer->movi_start)
- newpos = demuxer->movi_start; //begininng of stream
-
- stream_seek(demuxer->stream, newpos);
- for(i = 0; i < NB_PID_MAX; i++)
- if(priv->ts.pids[i] != NULL)
- priv->ts.pids[i]->is_synced = 0;
-
- videobuf_code_len = 0;
-
- if(sh_video != NULL)
- ds_fill_buffer(d_video);
-
- if(sh_audio != NULL)
- {
- ds_fill_buffer(d_audio);
- }
-
- while(sh_video != NULL)
- {
- if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts)
- {
- double a_pts=d_audio->pts;
- a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(double)sh_audio->i_bps;
- if(d_video->pts > a_pts)
- {
- skip_audio_frame(sh_audio); // sync audio
- continue;
- }
- }
-
-
- i = sync_video_packet(d_video);
- if((sh_video->format == VIDEO_MPEG1) || (sh_video->format == VIDEO_MPEG2))
- {
- if(i==0x1B3 || i==0x1B8) break; // found it!
- }
- else if((sh_video->format == VIDEO_MPEG4) && (i==0x1B6))
- break;
- else if(sh_video->format == VIDEO_VC1 && (i==0x10E || i==0x10F))
- break;
- else //H264
- {
- if((i & ~0x60) == 0x105 || (i & ~0x60) == 0x107) break;
- }
-
- if(!i || !skip_video_packet(d_video)) break; // EOF?
- }
-}
-
-
-static int demux_ts_fill_buffer(demuxer_t * demuxer, demux_stream_t *ds)
-{
- ES_stream_t es;
- ts_priv_t *priv = (ts_priv_t *)demuxer->priv;
-
- return -ts_parse(demuxer, &es, priv->packet, 0);
-}
-
-
-static int ts_check_file_dmx(demuxer_t *demuxer)
-{
- return ts_check_file(demuxer) ? DEMUXER_TYPE_MPEG_TS : 0;
-}
-
-static int is_usable_program(ts_priv_t *priv, pmt_t *pmt)
-{
- int j;
-
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(priv->ts.pids[pmt->es[j].pid] == NULL || priv->ts.streams[pmt->es[j].pid].sh == NULL)
- continue;
- if(
- priv->ts.streams[pmt->es[j].pid].type == TYPE_VIDEO ||
- priv->ts.streams[pmt->es[j].pid].type == TYPE_AUDIO
- )
- return 1;
- }
-
- return 0;
-}
-
-static int demux_ts_control(demuxer_t *demuxer, int cmd, void *arg)
-{
- ts_priv_t* priv = (ts_priv_t *)demuxer->priv;
-
- switch(cmd)
- {
- case DEMUXER_CTRL_SWITCH_AUDIO:
- case DEMUXER_CTRL_SWITCH_VIDEO:
- {
- void *sh = NULL;
- int i, n;
- int reftype, areset = 0, vreset = 0;
- demux_stream_t *ds;
-
- if(cmd == DEMUXER_CTRL_SWITCH_VIDEO)
- {
- reftype = TYPE_VIDEO;
- ds = demuxer->video;
- vreset = 1;
- }
- else
- {
- reftype = TYPE_AUDIO;
- ds = demuxer->audio;
- areset = 1;
- }
- n = *((int*)arg);
- if(n == -2)
- {
- reset_fifos(demuxer, areset, vreset, 0);
- ds->id = -2;
- ds->sh = NULL;
- ds_free_packs(ds);
- *((int*)arg) = ds->id;
- return DEMUXER_CTRL_OK;
- }
-
- if(n < 0)
- {
- for(i = 0; i < 8192; i++)
- {
- if(priv->ts.streams[i].id == ds->id && priv->ts.streams[i].type == reftype)
- break;
- }
-
- while(!sh)
- {
- i = (i+1) % 8192;
- if(priv->ts.streams[i].type == reftype)
- {
- if(priv->ts.streams[i].id == ds->id) //we made a complete loop
- break;
- sh = priv->ts.streams[i].sh;
- }
- }
- }
- else //audio track <n>
- {
- if (n >= 8192 || priv->ts.streams[n].type != reftype) return DEMUXER_CTRL_NOTIMPL;
- i = n;
- sh = priv->ts.streams[i].sh;
- }
-
- if(sh)
- {
- if(ds->id != priv->ts.streams[i].id)
- reset_fifos(demuxer, areset, vreset, 0);
- ds->id = priv->ts.streams[i].id;
- ds->sh = sh;
- ds_free_packs(ds);
- mp_msg(MSGT_DEMUX, MSGL_V, "\r\ndemux_ts, switched to audio pid %d, id: %d, sh: %p\r\n", i, ds->id, sh);
- }
-
- *((int*)arg) = ds->id;
- return DEMUXER_CTRL_OK;
- }
-
- case DEMUXER_CTRL_IDENTIFY_PROGRAM: //returns in prog->{aid,vid} the new ids that comprise a program
- {
- int i, j, cnt=0;
- int vid_done=0, aid_done=0;
- pmt_t *pmt = NULL;
- demux_program_t *prog = arg;
-
- if(priv->pmt_cnt < 2)
- return DEMUXER_CTRL_NOTIMPL;
-
- if(prog->progid == -1)
- {
- int cur_pmt_idx = 0;
-
- for(i = 0; i < priv->pmt_cnt; i++)
- if(priv->pmt[i].progid == priv->prog)
- {
- cur_pmt_idx = i;
- break;
- }
-
- i = (cur_pmt_idx + 1) % priv->pmt_cnt;
- while(i != cur_pmt_idx)
- {
- pmt = &priv->pmt[i];
- cnt = is_usable_program(priv, pmt);
- if(cnt)
- break;
- i = (i + 1) % priv->pmt_cnt;
- }
- }
- else
- {
- for(i = 0; i < priv->pmt_cnt; i++)
- if(priv->pmt[i].progid == prog->progid)
- {
- pmt = &priv->pmt[i]; //required program
- cnt = is_usable_program(priv, pmt);
- }
- }
-
- if(!cnt)
- return DEMUXER_CTRL_NOTIMPL;
-
- //finally some food
- prog->aid = prog->vid = -2; //no audio and no video by default
- for(j = 0; j < pmt->es_cnt; j++)
- {
- if(priv->ts.pids[pmt->es[j].pid] == NULL || priv->ts.streams[pmt->es[j].pid].sh == NULL)
- continue;
-
- if(!vid_done && priv->ts.streams[pmt->es[j].pid].type == TYPE_VIDEO)
- {
- vid_done = 1;
- prog->vid = pmt->es[j].pid;
- }
- else if(!aid_done && priv->ts.streams[pmt->es[j].pid].type == TYPE_AUDIO)
- {
- aid_done = 1;
- prog->aid = pmt->es[j].pid;
- }
- }
-
- priv->prog = prog->progid = pmt->progid;
- return DEMUXER_CTRL_OK;
- }
-
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-
-const demuxer_desc_t demuxer_desc_mpeg_ts = {
- "MPEG-TS demuxer",
- "mpegts",
- "TS",
- "Nico Sabbi",
- "",
- DEMUXER_TYPE_MPEG_TS,
- 0, // unsafe autodetect
- ts_check_file_dmx,
- demux_ts_fill_buffer,
- demux_open_ts,
- demux_close_ts,
- demux_seek_ts,
- demux_ts_control
-};
diff --git a/libmpdemux/demux_ts.h b/libmpdemux/demux_ts.h
deleted file mode 100644
index 37bddb86da..0000000000
--- a/libmpdemux/demux_ts.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_DEMUX_TS_H
-#define MPLAYER_DEMUX_TS_H
-
-#define TS_MAX_PROBE_SIZE 2000000
-
-#endif /* MPLAYER_DEMUX_TS_H */
diff --git a/libmpdemux/demux_ty.c b/libmpdemux/demux_ty.c
deleted file mode 100644
index 527d350bc6..0000000000
--- a/libmpdemux/demux_ty.c
+++ /dev/null
@@ -1,899 +0,0 @@
-/*
- * tivo@wingert.org, February 2003
- *
- * Copyright (C) 2003 Christopher R. Wingert
- *
- * The license covers the portions of this file regarding TiVo additions.
- *
- * Olaf Beck and Tridge (indirectly) were essential at providing
- * information regarding the format of the TiVo streams.
- *
- * However, no code in the following subsection is directly copied from
- * either author.
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <stdarg.h>
-
-#include <libavutil/avstring.h>
-#include <libavutil/intreadwrite.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "libmpcodecs/dec_audio.h"
-#include "stream/stream.h"
-#include "demuxer.h"
-#ifdef DEMUX_TY_OSD
-#include "demux_ty_osd.h"
-#endif
-#include "parse_es.h"
-#include "stheader.h"
-#include "sub/sub_cc.h"
-#include "sub/sub.h"
-
-// 2/c0: audio data
-// 3/c0: audio packet header (PES header)
-// 4/c0: audio data (S/A only?)
-// 9/c0: audio packet header, AC-3 audio
-// 2/e0: video data
-// 6/e0: video packet header (PES header)
-// 7/e0: video sequence header start
-// 8/e0: video I-frame header start
-// a/e0: video P-frame header start
-// b/e0: video B-frame header start
-// c/e0: video GOP header start
-// e/01: closed-caption data
-// e/02: Extended data services data
-
-
-#define TIVO_PES_FILEID 0xf5467abd
-#define TIVO_PART_LENGTH 0x20000000
-
-#define CHUNKSIZE ( 128 * 1024 )
-#define MAX_AUDIO_BUFFER ( 16 * 1024 )
-
-#define TY_V 1
-#define TY_A 2
-
-typedef struct
-{
- off_t startOffset;
- off_t fileSize;
- int chunks;
-} tmf_fileParts;
-
-#define MAX_TMF_PARTS 16
-
-typedef struct
-{
- int whichChunk;
- unsigned char chunk[ CHUNKSIZE ];
-
- unsigned char lastAudio[ MAX_AUDIO_BUFFER ];
- int lastAudioEnd;
-
- int tivoType; // 1 = SA, 2 = DTiVo
-
- int64_t lastAudioPTS;
- int64_t lastVideoPTS;
-
- off_t size;
- int readHeader;
-
- int tmf;
- tmf_fileParts tmfparts[ MAX_TMF_PARTS ];
- int tmf_totalparts;
-} TiVoInfo;
-
-// ===========================================================================
-#define TMF_SIG "showing.xml"
-
-// ===========================================================================
-static int ty_tmf_filetoparts( demuxer_t *demux, TiVoInfo *tivo )
-{
- int parts = 0;
-
- stream_seek(demux->stream, 0);
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "Dumping tar contents\n" );
- while (!demux->stream->eof)
- {
- char header[ 512 ];
- char *name;
- char *extension;
- char *sizestr;
- int size;
- off_t skip;
- if (stream_read(demux->stream, header, 512) < 512)
- {
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "Read bad\n" );
- break;
- }
- name = header;
- name[99] = 0;
- sizestr = &header[124];
- sizestr[11] = 0;
- size = strtol(sizestr, NULL, 8);
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "name %-20.20s size %-12.12s %d\n",
- name, sizestr, size );
-
- extension = strrchr(name, '.');
- if (extension && strcmp(extension, ".ty") == 0)
- {
- if ( parts >= MAX_TMF_PARTS ) {
- mp_msg( MSGT_DEMUX, MSGL_ERR, "ty:tmf too big\n" );
- break;
- }
- tivo->tmfparts[ parts ].fileSize = size;
- tivo->tmfparts[ parts ].startOffset = stream_tell(demux->stream);
- tivo->tmfparts[ parts ].chunks = size / CHUNKSIZE;
- mp_msg(MSGT_DEMUX, MSGL_DBG3,
- "tmf_filetoparts(): index %d, chunks %d\n"
- "tmf_filetoparts(): size %"PRId64"\n"
- "tmf_filetoparts(): startOffset %"PRId64"\n",
- parts, tivo->tmfparts[ parts ].chunks,
- tivo->tmfparts[ parts ].fileSize, tivo->tmfparts[ parts ].startOffset
- );
- parts++;
- }
-
- // size rounded up to blocks
- skip = (size + 511) & ~511;
- stream_skip(demux->stream, skip);
- }
- stream_reset(demux->stream);
- tivo->tmf_totalparts = parts;
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "tmf_filetoparts(): No More Part Files %d\n", parts );
-
- return 1;
-}
-
-
-// ===========================================================================
-static off_t tmf_filetooffset(TiVoInfo *tivo, int chunk)
-{
- int i;
- for (i = 0; i < tivo->tmf_totalparts; i++) {
- if (chunk < tivo->tmfparts[i].chunks)
- return tivo->tmfparts[i].startOffset + chunk * CHUNKSIZE;
- chunk -= tivo->tmfparts[i].chunks;
- }
- return -1;
-}
-
-
-// ===========================================================================
-static int tmf_load_chunk( demuxer_t *demux, TiVoInfo *tivo,
- unsigned char *buff, int readChunk )
-{
- off_t fileoffset;
- int count;
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "\ntmf_load_chunk() begin %d\n",
- readChunk );
-
- fileoffset = tmf_filetooffset(tivo, readChunk);
-
- if (fileoffset == -1 || !stream_seek(demux->stream, fileoffset)) {
- mp_msg( MSGT_DEMUX, MSGL_ERR, "Read past EOF()\n" );
- return 0;
- }
- count = stream_read( demux->stream, buff, CHUNKSIZE );
- demux->filepos = stream_tell( demux->stream );
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "tmf_load_chunk() count %x\n",
- count );
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "tmf_load_chunk() bytes %x %x %x %x %x %x %x %x\n",
- buff[ 0 ], buff[ 1 ], buff[ 2 ], buff[ 3 ],
- buff[ 4 ], buff[ 5 ], buff[ 6 ], buff[ 7 ] );
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "tmf_load_chunk() end\n" );
-
- return count;
-}
-
-// ===========================================================================
-
-// DTiVo MPEG 336, 480, 576, 768
-// SA TiVo 864
-// DTiVo AC-3 1550
-//
-#define SERIES1_PTS_LENGTH 11
-#define SERIES1_PTS_OFFSET 6
-#define SERIES2_PTS_LENGTH 16
-#define SERIES2_PTS_OFFSET 9
-#define AC3_PTS_LENGTH 16
-#define AC3_PTS_OFFSET 9
-
-static int IsValidAudioPacket( int size, int *ptsOffset, int *ptsLen )
-{
- // AC-3
- if ( size == 1550 || size == 1552 )
- {
- *ptsOffset = AC3_PTS_OFFSET;
- *ptsLen = AC3_PTS_LENGTH;
- return 1;
- }
-
- // MPEG
- if ( (size & 15) == (SERIES1_PTS_LENGTH & 15) )
- {
- *ptsOffset = SERIES1_PTS_OFFSET;
- *ptsLen = SERIES1_PTS_LENGTH;
- return 1;
- }
- if ( (size & 15) == (SERIES2_PTS_LENGTH & 15) )
- {
- *ptsOffset = SERIES2_PTS_OFFSET;
- *ptsLen = SERIES2_PTS_LENGTH;
- return 1;
- }
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Tossing Audio Packet Size %d\n",
- size );
- return 0;
-}
-
-
-static int64_t get_ty_pts( unsigned char *buf )
-{
- int a = buf[0] & 0xe;
- int b = AV_RB16(buf + 1);
- int c = AV_RB16(buf + 3);
-
- if (!(1 & a & b & c)) // invalid MPEG timestamp
- return MP_NOPTS_VALUE;
- a >>= 1; b >>= 1; c >>= 1;
- return (((uint64_t)a) << 30) | (b << 15) | c;
-}
-
-static void demux_ty_AddToAudioBuffer( TiVoInfo *tivo, unsigned char *buffer,
- int size )
-{
- if ( tivo->lastAudioEnd + size < MAX_AUDIO_BUFFER )
- {
- memcpy( &tivo->lastAudio[ tivo->lastAudioEnd ],
- buffer, size );
- tivo->lastAudioEnd += size;
- }
- else
- mp_msg( MSGT_DEMUX, MSGL_ERR,
- "ty:WARNING - Would have blown my audio buffer\n" );
-}
-
-static void demux_ty_CopyToDemuxPacket( demux_stream_t *ds,
- unsigned char *buffer, int size, off_t pos, int64_t pts )
-{
- demux_packet_t *dp = new_demux_packet( size );
- memcpy( dp->buffer, buffer, size );
- if (pts != MP_NOPTS_VALUE)
- dp->pts = pts / 90000.0;
- dp->pos = pos;
- ds_add_packet( ds, dp );
-}
-
-static int demux_ty_FindESHeader( uint8_t nal,
- unsigned char *buffer, int bufferSize )
-{
- uint32_t search = 0x00000100 | nal;
- uint32_t found = -1;
- uint8_t *p = buffer;
- uint8_t *end = p + bufferSize;
- while (p < end) {
- found <<= 8;
- found |= *p++;
- if (found == search)
- return p - buffer - 4;
- }
- return -1;
-}
-
-static void demux_ty_FindESPacket( uint8_t nal,
- unsigned char *buffer, int bufferSize, int *esOffset1, int *esOffset2 )
-{
- *esOffset1 = demux_ty_FindESHeader(nal, buffer, bufferSize);
- if (*esOffset1 == -1) {
- *esOffset2 = -1;
- return;
- }
- buffer += *esOffset1 + 1;
- bufferSize -= *esOffset1 + 1;
- *esOffset2 = demux_ty_FindESHeader(nal, buffer, bufferSize);
- if (*esOffset2 != -1)
- *esOffset2 += *esOffset1 + 1;
-}
-
-#define VIDEO_NAL 0xe0
-#define AUDIO_NAL 0xc0
-#define AC3_NAL 0xbd
-
-static int demux_ty_fill_buffer( demuxer_t *demux, demux_stream_t *dsds )
-{
- int invalidType = 0;
- int errorHeader = 0;
- int recordsDecoded = 0;
-
- int readSize;
-
- int numberRecs;
- unsigned char *recPtr;
- int offset;
-
- int counter;
-
- int aid;
-
- TiVoInfo *tivo = demux->priv;
- unsigned char *chunk = tivo->chunk;
-
- if ( demux->stream->type == STREAMTYPE_DVD )
- return 0;
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty processing\n" );
-
- if( demux->stream->eof ) return 0;
-
- // ======================================================================
- // If we haven't figured out the size of the stream, let's do so
- // ======================================================================
- if ( demux->stream->type == STREAMTYPE_VSTREAM )
- {
- // The vstream code figures out the exact size of the stream
- demux->movi_start = 0;
- demux->movi_end = demux->stream->end_pos;
- tivo->size = demux->stream->end_pos;
- }
- else
- {
- // If its a local file, try to find the Part Headers, so we can
- // calculate the ACTUAL stream size
- // If we can't find it, go off with the file size and hope the
- // extract program did the "right thing"
- if ( tivo->readHeader == 0 )
- {
- off_t filePos;
- tivo->readHeader = 1;
-
- filePos = demux->filepos;
- stream_seek( demux->stream, 0 );
-
- readSize = stream_read( demux->stream, chunk, CHUNKSIZE );
-
- if ( memcmp( chunk, TMF_SIG, sizeof( TMF_SIG ) ) == 0 )
- {
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Detected a tmf\n" );
- tivo->tmf = 1;
- ty_tmf_filetoparts( demux, tivo );
- readSize = tmf_load_chunk( demux, tivo, chunk, 0 );
- }
-
- if ( readSize == CHUNKSIZE && AV_RB32(chunk) == TIVO_PES_FILEID )
- {
- off_t numberParts;
-
- readSize = 0;
-
- if ( tivo->tmf != 1 )
- {
- off_t offset;
-
- numberParts = demux->stream->end_pos / TIVO_PART_LENGTH;
- offset = numberParts * TIVO_PART_LENGTH;
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty/ty+Number Parts %"PRId64"\n",
- (int64_t)numberParts );
-
- if ( offset + CHUNKSIZE < demux->stream->end_pos )
- {
- stream_seek( demux->stream, offset );
- readSize = stream_read( demux->stream, chunk, CHUNKSIZE );
- }
- }
- else
- {
- numberParts = tivo->tmf_totalparts;
- offset = numberParts * TIVO_PART_LENGTH;
- readSize = tmf_load_chunk( demux, tivo, chunk,
- numberParts * ( TIVO_PART_LENGTH - CHUNKSIZE ) /
- CHUNKSIZE );
- }
-
- if ( readSize == CHUNKSIZE && AV_RB32(chunk) == TIVO_PES_FILEID )
- {
- int size = AV_RB24(chunk + 12);
- size -= 4;
- size *= CHUNKSIZE;
- tivo->size = numberParts * TIVO_PART_LENGTH;
- tivo->size += size;
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "ty:Header Calc Stream Size %"PRId64"\n", tivo->size );
- }
- }
-
- if ( demux->stream->start_pos > 0 )
- filePos = demux->stream->start_pos;
- stream_seek( demux->stream, filePos );
- demux->filepos = stream_tell( demux->stream );
- tivo->whichChunk = filePos / CHUNKSIZE;
- }
- demux->movi_start = 0;
- demux->movi_end = tivo->size;
- }
-
- // ======================================================================
- // Give a clue as to where we are in the stream
- // ======================================================================
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "ty:ty header size %"PRIx64"\n", (int64_t)tivo->size );
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "ty:ty which Chunk %d\n", tivo->whichChunk );
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "ty:file end_pos %"PRIx64"\n", (int64_t)demux->stream->end_pos );
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "\nty:wanted current offset %"PRIx64"\n", (int64_t)stream_tell( demux->stream ) );
-
- if ( tivo->size > 0 && stream_tell( demux->stream ) > tivo->size )
- {
- demux->stream->eof = 1;
- return 0;
- }
-
- do {
- if ( tivo->tmf != 1 )
- {
- // Make sure we are on a 128k boundary
- if ( demux->filepos % CHUNKSIZE != 0 )
- {
- int whichChunk = demux->filepos / CHUNKSIZE;
- if ( demux->filepos % CHUNKSIZE > CHUNKSIZE / 2 )
- whichChunk++;
- stream_seek( demux->stream, whichChunk * CHUNKSIZE );
- }
-
- demux->filepos = stream_tell( demux->stream );
- tivo->whichChunk = demux->filepos / CHUNKSIZE;
- readSize = stream_read( demux->stream, chunk, CHUNKSIZE );
- if ( readSize != CHUNKSIZE )
- return 0;
- }
- else
- {
- readSize = tmf_load_chunk( demux, tivo, chunk, tivo->whichChunk );
- if ( readSize != CHUNKSIZE )
- return 0;
- tivo->whichChunk++;
- }
- if (AV_RB32(chunk) == TIVO_PES_FILEID)
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Skipping PART Header\n" );
- } while (AV_RB32(chunk) == TIVO_PES_FILEID);
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "\nty:actual current offset %"PRIx64"\n", stream_tell( demux->stream ) -
- CHUNKSIZE );
-
-
- // Let's make a Video Demux Stream for MPlayer
- aid = 0x0;
- if( !demux->v_streams[ aid ] ) new_sh_video( demux, aid );
- if( demux->video->id == -1 ) demux->video->id = aid;
- if( demux->video->id == aid )
- {
- demux_stream_t *ds = demux->video;
- if( !ds->sh ) ds->sh = demux->v_streams[ aid ];
- }
-
- // ======================================================================
- // Finally, we get to actually parse the chunk
- // ======================================================================
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty parsing a chunk\n" );
- numberRecs = chunk[ 0 ];
- recPtr = &chunk[ 4 ];
- offset = numberRecs * 16 + 4;
- for ( counter = 0 ; counter < numberRecs ; counter++ )
- {
- int size = AV_RB24(recPtr) >> 4;
- int type = recPtr[ 3 ];
- int nybbleType = recPtr[ 2 ] & 0x0f;
- recordsDecoded++;
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "ty:Record Type %x/%x %d\n", nybbleType, type, size );
-
- // ================================================================
- // Video Parsing
- // ================================================================
- if ( type == 0xe0 )
- {
- if ( size > 0 && size + offset <= CHUNKSIZE )
- {
- int esOffset1 = demux_ty_FindESHeader( VIDEO_NAL, &chunk[ offset ],
- size);
- if ( esOffset1 != -1 )
- tivo->lastVideoPTS = get_ty_pts(
- &chunk[ offset + esOffset1 + 9 ] );
-
- // Do NOT Pass the PES Header onto the MPEG2 Decode
- if( nybbleType != 0x06 )
- demux_ty_CopyToDemuxPacket( demux->video,
- &chunk[ offset ], size, demux->filepos + offset,
- tivo->lastVideoPTS );
- offset += size;
- }
- else
- errorHeader++;
- }
- // ================================================================
- // Audio Parsing
- // ================================================================
- else if ( type == 0xc0 )
- {
- if ( size > 0 && size + offset <= CHUNKSIZE )
- {
- if( demux->audio->id == -1 )
- {
- if ( nybbleType == 0x02 )
- continue; // DTiVo inconclusive, wait for more
- else if ( nybbleType == 0x09 )
- {
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Setting AC-3 Audio\n" );
- aid = 0x80; // AC-3
- }
- else
- {
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Setting MPEG Audio\n" );
- aid = 0x0; // MPEG Audio
- }
-
- demux->audio->id = aid;
- if( !demux->a_streams[ aid ] ) new_sh_audio( demux, aid );
- if( demux->audio->id == aid )
- {
- demux_stream_t *ds = demux->audio;
- if( !ds->sh ) {
- sh_audio_t* sh_a;
- ds->sh = demux->a_streams[ aid ];
- sh_a = (sh_audio_t*)ds->sh;
- switch(aid & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id)
- case 0x00: sh_a->format=0x50;break; // mpeg
- case 0xA0: sh_a->format=0x10001;break; // dvd pcm
- case 0x80: if((aid & 0xF8) == 0x88) sh_a->format=0x2001;//dts
- else sh_a->format=0x2000;break; // ac3
- }
- }
- }
- }
-
- aid = demux->audio->id;
-
-
- // SA DTiVo Audio Data, no PES
- // ================================================
- if ( nybbleType == 0x02 || nybbleType == 0x04 )
- {
- if ( nybbleType == 0x02 && tivo->tivoType == 2 )
- demux_ty_AddToAudioBuffer( tivo, &chunk[ offset ], size );
- else
- {
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "ty:Adding Audio Packet Size %d\n", size );
- demux_ty_CopyToDemuxPacket( demux->audio,
- &chunk[ offset ], size, ( demux->filepos + offset ),
- tivo->lastAudioPTS );
- }
- }
-
- // 3 - MPEG Audio with PES Header, either SA or DTiVo
- // 9 - DTiVo AC3 Audio Data with PES Header
- // ================================================
- if ( nybbleType == 0x03 || nybbleType == 0x09 )
- {
- int esOffset1, esOffset2;
- if ( nybbleType == 0x03 )
- esOffset1 = demux_ty_FindESHeader( AUDIO_NAL, &chunk[ offset ],
- size);
-
- // SA PES Header, No Audio Data
- // ================================================
- if ( nybbleType == 0x03 && esOffset1 == 0 && size == 16 )
- {
- tivo->tivoType = 1;
- tivo->lastAudioPTS = get_ty_pts( &chunk[ offset +
- SERIES2_PTS_OFFSET ] );
- }
- else
- // DTiVo Audio with PES Header
- // ================================================
- {
- tivo->tivoType = 2;
-
- demux_ty_AddToAudioBuffer( tivo, &chunk[ offset ], size );
- demux_ty_FindESPacket( nybbleType == 9 ? AC3_NAL : AUDIO_NAL,
- tivo->lastAudio, tivo->lastAudioEnd, &esOffset1,
- &esOffset2 );
-
- if ( esOffset1 != -1 && esOffset2 != -1 )
- {
- int packetSize = esOffset2 - esOffset1;
- int headerSize;
- int ptsOffset;
-
- if ( IsValidAudioPacket( packetSize, &ptsOffset,
- &headerSize ) )
- {
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "ty:Adding DTiVo Audio Packet Size %d\n",
- packetSize );
-
- tivo->lastAudioPTS = get_ty_pts(
- &tivo->lastAudio[ esOffset1 + ptsOffset ] );
-
- if (nybbleType == 9) headerSize = 0;
- demux_ty_CopyToDemuxPacket
- (
- demux->audio,
- &tivo->lastAudio[ esOffset1 + headerSize ],
- packetSize - headerSize,
- demux->filepos + offset,
- tivo->lastAudioPTS
- );
-
- }
-
- // Collapse the Audio Buffer
- tivo->lastAudioEnd -= esOffset2;
- memmove( &tivo->lastAudio[ 0 ],
- &tivo->lastAudio[ esOffset2 ],
- tivo->lastAudioEnd );
- }
- }
- }
-
- offset += size;
- }
- else
- errorHeader++;
- }
- // ================================================================
- // 1 = Closed Caption
- // 2 = Extended Data Services
- // ================================================================
- else if ( type == 0x01 || type == 0x02 )
- {
- unsigned char lastXDS[ 16 ];
- int b = AV_RB24(recPtr) >> 4;
- b &= 0x7f7f;
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:%s %04x\n", type == 1 ? "CC" : "XDS", b);
-
- lastXDS[ 0x00 ] = 0x00;
- lastXDS[ 0x01 ] = 0x00;
- lastXDS[ 0x02 ] = 0x01;
- lastXDS[ 0x03 ] = 0xb2;
- lastXDS[ 0x04 ] = 'T';
- lastXDS[ 0x05 ] = 'Y';
- lastXDS[ 0x06 ] = type;
- lastXDS[ 0x07 ] = b >> 8;
- lastXDS[ 0x08 ] = b;
- if ( subcc_enabled )
- demux_ty_CopyToDemuxPacket( demux->video, lastXDS, 0x09,
- demux->filepos + offset, tivo->lastVideoPTS );
- }
- // ================================================================
- // Unknown
- // ================================================================
- else
- {
- if ( size > 0 && size + offset <= CHUNKSIZE )
- offset += size;
- if (type != 3 && type != 5 && (type != 0 || size > 0)) {
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Invalid Type %x\n", type );
- invalidType++;
- }
- }
- recPtr += 16;
- }
-
- if ( errorHeader > 0 || invalidType > 0 )
- {
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "ty:Error Check - Records %d, Parsed %d, Errors %d + %d\n",
- numberRecs, recordsDecoded, errorHeader, invalidType );
-
- // Invalid MPEG ES Size Check
- if ( errorHeader > numberRecs / 2 )
- return 0;
-
- // Invalid MPEG Stream Type Check
- if ( invalidType > numberRecs / 2 )
- return 0;
- }
-
- demux->filepos = stream_tell( demux->stream );
-
- return 1;
-}
-
-static void demux_seek_ty( demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags )
-{
- demux_stream_t *d_audio = demuxer->audio;
- demux_stream_t *d_video = demuxer->video;
- sh_audio_t *sh_audio = d_audio->sh;
- sh_video_t *sh_video = d_video->sh;
- off_t newpos;
- off_t res;
- TiVoInfo *tivo = demuxer->priv;
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Seeking to %7.1f\n", rel_seek_secs );
-
- tivo->lastAudioEnd = 0;
- tivo->lastAudioPTS = MP_NOPTS_VALUE;
- tivo->lastVideoPTS = MP_NOPTS_VALUE;
- //
- //================= seek in MPEG ==========================
- demuxer->filepos = stream_tell( demuxer->stream );
-
- newpos = ( flags & SEEK_ABSOLUTE ) ? demuxer->movi_start : demuxer->filepos;
-
- if( flags & SEEK_FACTOR )
- // float seek 0..1
- newpos += ( demuxer->movi_end - demuxer->movi_start ) * rel_seek_secs;
- else
- {
- // time seek (secs)
- if( ! sh_video->i_bps ) // unspecified or VBR
- newpos += 2324 * 75 * rel_seek_secs; // 174.3 kbyte/sec
- else
- newpos += sh_video->i_bps * rel_seek_secs;
- }
-
- if ( newpos < demuxer->movi_start )
- {
- if( demuxer->stream->type != STREAMTYPE_VCD ) demuxer->movi_start = 0;
- if( newpos < demuxer->movi_start ) newpos = demuxer->movi_start;
- }
-
- res = newpos / CHUNKSIZE;
- if ( rel_seek_secs >= 0 )
- newpos = ( res + 1 ) * CHUNKSIZE;
- else
- newpos = res * CHUNKSIZE;
-
- if ( newpos < 0 )
- newpos = 0;
-
- tivo->whichChunk = newpos / CHUNKSIZE;
-
- stream_seek( demuxer->stream, newpos );
-
- // re-sync video:
- videobuf_code_len = 0; // reset ES stream buffer
-
- ds_fill_buffer( d_video );
- if( sh_audio )
- ds_fill_buffer( d_audio );
-
- while( 1 )
- {
- int i;
- if( sh_audio && !d_audio->eof && d_video->pts && d_audio->pts )
- {
- float a_pts = d_audio->pts;
- a_pts += ( ds_tell_pts( d_audio ) - sh_audio->a_in_buffer_len ) /
- (float)sh_audio->i_bps;
- if( d_video->pts > a_pts )
- {
- skip_audio_frame( sh_audio ); // sync audio
- continue;
- }
- }
- i = sync_video_packet( d_video );
- if( i == 0x1B3 || i == 0x1B8 ) break; // found it!
- if( !i || !skip_video_packet( d_video ) ) break; // EOF?
- }
-#ifdef DEMUX_TY_OSD
- if ( subcc_enabled )
- ty_ClearOSD( 0 );
-#endif
-}
-
-static int demux_ty_control( demuxer_t *demuxer,int cmd, void *arg )
-{
- demux_stream_t *d_video = demuxer->video;
- sh_video_t *sh_video = d_video->sh;
-
- switch(cmd)
- {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- if(!sh_video->i_bps) // unspecified or VBR
- return DEMUXER_CTRL_DONTKNOW;
- *(double *)arg=
- (double)demuxer->movi_end-demuxer->movi_start/sh_video->i_bps;
- return DEMUXER_CTRL_GUESS;
-
- case DEMUXER_CTRL_GET_PERCENT_POS:
- return DEMUXER_CTRL_DONTKNOW;
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-
-static void demux_close_ty( demuxer_t *demux )
-{
- TiVoInfo *tivo = demux->priv;
-
- free( tivo );
- sub_justify = 0;
-}
-
-
-static int ty_check_file(demuxer_t* demuxer)
-{
- demuxer->filepos = 0;
- TiVoInfo *tivo = calloc(1, sizeof(TiVoInfo));
- demuxer->priv = tivo;
- return ds_fill_buffer(demuxer->video) ? DEMUXER_TYPE_MPEG_TY : 0;
-}
-
-
-static demuxer_t* demux_open_ty(demuxer_t* demuxer)
-{
- sh_audio_t *sh_audio=NULL;
- sh_video_t *sh_video=NULL;
-
- sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
-
- if(demuxer->audio->id!=-2) {
- if(!ds_fill_buffer(demuxer->audio)){
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "MPEG: %s",
- mp_gtext("No audio stream found -> no sound.\n"));
- demuxer->audio->sh=NULL;
- } else {
- sh_audio=demuxer->audio->sh;sh_audio->ds=demuxer->audio;
- }
- }
-
- return demuxer;
-}
-
-
-const demuxer_desc_t demuxer_desc_mpeg_ty = {
- "TiVo demuxer",
- "tivo",
- "TiVo",
- "Christopher R. Wingert",
- "Demux streams from TiVo",
- DEMUXER_TYPE_MPEG_TY,
- 0, // unsafe autodetect
- ty_check_file,
- demux_ty_fill_buffer,
- demux_open_ty,
- demux_close_ty,
- demux_seek_ty,
- demux_ty_control
-};
diff --git a/libmpdemux/demux_ty_osd.c b/libmpdemux/demux_ty_osd.c
deleted file mode 100644
index 983c243f98..0000000000
--- a/libmpdemux/demux_ty_osd.c
+++ /dev/null
@@ -1,911 +0,0 @@
-// Most of this was written by Mike Baker <mbm@linux.com>
-// and released under the GPL v2+ license.
-//
-// Modifications and SEVERE cleanup of the code was done by
-// Christopher Wingert
-// Copyright 2003
-//
-// Released under GPL2 License.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-//#include "stream/stream.h"
-//#include "demuxer.h"
-//#include "parse_es.h"
-//#include "stheader.h"
-//#include "mp3_hdr.h"
-//#include "subreader.h"
-#include "sub/sub_cc.h"
-#include "sub/sub.h"
-#include "demux_ty_osd.h"
-
-//#include "dvdauth.h"
-
-extern int sub_justify;
-
-#define TY_TEXT_MODE ( 1 << 0 )
-#define TY_OSD_MODE ( 1 << 1 )
-
-static int TY_OSD_flags = TY_TEXT_MODE | TY_OSD_MODE;
-static int TY_OSD_debug = 0;
-
-// ===========================================================================
-// Closed Caption Decoding and OSD Presentation
-// ===========================================================================
-#define TY_CCNONE ( -3 )
-#define TY_CCTEXTMODE ( -2 )
-#define TY_CCPOPUPNB ( -1 )
-#define TY_CCPOPUP ( 0 )
-#define TY_CCPAINTON ( 1 )
-
-#define TY_CC_MAX_X ( 45 )
-
-static int TY_CC_CUR_X;
-static int TY_CC_CUR_Y;
-static int TY_CC_stat = TY_CCNONE;
-static char TY_CC_buf[ 255 ];
-static char *TY_CC_ptr = TY_CC_buf;
-static unsigned TY_CC_lastcap = 0;
-static int TY_CC_TextItalic;
-static int TY_CC_Y_Offset;
-
-static subtitle ty_OSD1;
-static subtitle ty_OSD2;
-static subtitle *ty_pOSD1;
-static subtitle *ty_pOSD2;
-static int tyOSDInitialized = 0;
-static int tyOSDUpdate = 0;
-
-static void ty_DrawOSD(void)
-{
- // printf( "Calling ty_DrawOSD()\n" );
- tyOSDUpdate = 1;
-}
-
-void ty_ClearOSD( int start )
-{
- int index;
- // printf( "Calling ty_ClearOSD()\n" );
- for ( index = start ; index < SUB_MAX_TEXT ; index++ )
- {
- memset( ty_OSD1.text[ index ], ' ', TY_CC_MAX_X - 1 );
- ty_OSD1.text[ index ][ TY_CC_MAX_X - 1 ] = 0;
- memset( ty_OSD2.text[ index ], ' ', TY_CC_MAX_X - 1 );
- ty_OSD2.text[ index ][ TY_CC_MAX_X - 1 ] = 0;
- }
-}
-
-static void ty_DrawChar( int *x, int *y, char disChar, int fgColor, int bgColor )
-{
- int cx;
- int cy;
-
- cx = *x;
- cy = *y;
-
- if ( *x >= ( TY_CC_MAX_X - 1 ) )
- {
- cx = 0;
- }
- if ( ( *y + TY_CC_Y_Offset ) > SUB_MAX_TEXT )
- {
- cy = SUB_MAX_TEXT - TY_CC_Y_Offset - 1;
- }
-
- // printf( "Calling ty_DrawChar() x:%d y:%d %c fg:%d bg:%d\n",
- // cx, cy, disChar, fgColor, bgColor );
-
- ty_OSD1.text[ TY_CC_Y_Offset + cy ][ cx ] = disChar;
- memset( &( ty_OSD1.text[ TY_CC_Y_Offset + cy ][ cx + 1 ] ), ' ',
- TY_CC_MAX_X - cx - 2 );
- ( *x )++;
-}
-
-static void ty_RollupBuf( int dest, int source, int numLines )
-{
- int index;
-
- // printf( "Calling ty_RollupBuf() dest:%d source %d, numLines %d\n",
- // dest, source, numLines );
- //
- if ( ( source + TY_CC_Y_Offset + numLines ) > SUB_MAX_TEXT )
- {
- ty_ClearOSD( 1 );
- return;
- }
-
- if ( ( source + TY_CC_Y_Offset + numLines ) < 0 )
- {
- ty_ClearOSD( 1 );
- return;
- }
-
- if ( numLines > SUB_MAX_TEXT )
- {
- ty_ClearOSD( 1 );
- return;
- }
-
- for ( index = 0 ; index < numLines ; index++ )
- {
- strcpy( ty_OSD1.text[ TY_CC_Y_Offset + dest ],
- ty_OSD1.text[ TY_CC_Y_Offset + source ] );
- dest++;
- source++;
- }
- memset( ty_OSD1.text[ TY_CC_Y_Offset + source - 1 ], ' ', TY_CC_MAX_X - 1 );
- ty_OSD1.text[ TY_CC_Y_Offset + source - 1 ][ TY_CC_MAX_X - 1 ] = 0;
-}
-
-static void ty_drawchar( char c )
-{
- if ( c < 2 ) return;
-
- if ( TY_OSD_flags & TY_OSD_MODE && TY_CC_stat != TY_CCNONE &&
- TY_CC_CUR_Y != -1 )
- ty_DrawChar( &TY_CC_CUR_X, &TY_CC_CUR_Y, c, 4, 13 );
-
- if ( TY_CC_ptr - TY_CC_buf > sizeof( TY_CC_buf ) - 1 )
- { // buffer overflow
- TY_CC_ptr = TY_CC_buf;
- memset( TY_CC_buf, 0, sizeof( TY_CC_buf ) );
- }
- *( TY_CC_ptr++ ) = ( c == 14 ) ? '/' : c; // swap a '/' for musical note
-}
-
-static void ty_draw(void)
-{
- if ( TY_CC_ptr != TY_CC_buf && TY_OSD_flags & TY_TEXT_MODE )
- {
- if ( *( TY_CC_ptr - 1 ) == '\n' ) *( TY_CC_ptr - 1 ) = 0;
-
- mp_msg( MSGT_DEMUX, MSGL_V, "CC: %s\n", TY_CC_buf );
- }
- TY_CC_lastcap = time( NULL );
-
- TY_CC_ptr = TY_CC_buf;
- memset( TY_CC_buf, 0, sizeof( TY_CC_buf) );
-
- if ( TY_OSD_flags & TY_OSD_MODE ) ty_DrawOSD();
- if ( TY_CC_TextItalic ) TY_CC_TextItalic = 0;
-}
-
-
-static int CC_last = 0;
-static char CC_mode = 0;
-static int CC_row[] =
-{
- 11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9, 10
-};
-
-// char specialchar[] = { '®', '°', '½', '¿', '*', '¢', '£', 14, 'à', ' ', 'è', 'â', 'ê', 'î', 'ô', 'û' };
-
-static int ty_CCdecode( char b1, char b2 )
-{
- int x;
- int data = ( b2 << 8 ) + b1;
-
- if ( b1 & 0x60 ) // text
- {
- if ( !TY_OSD_debug && TY_CC_stat == TY_CCNONE ) return 0;
- if ( TY_OSD_debug > 3 )
- {
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "%c %c", b1, b2 );
- }
- ty_drawchar( b1 );
- ty_drawchar( b2 );
-
- if ( TY_CC_stat > 0 && TY_OSD_flags & TY_OSD_MODE ) ty_DrawOSD();
- }
- else if ( ( b1 & 0x10 ) && ( b2 > 0x1F ) && ( data != CC_last ) )
- {
- #define CURRENT ( ( b1 & 0x08 ) >> 3 )
-
- if ( CC_mode != CURRENT && TY_CC_stat != TY_CCNONE )
- {
- if ( TY_OSD_debug && TY_CC_ptr != TY_CC_buf ) ty_draw();
- TY_CC_stat = TY_CCNONE;
- return 0;
- }
-
- if ( TY_CC_stat == TY_CCNONE || TY_CC_CUR_Y == -1 )
- {
- if ( TY_CC_ptr != TY_CC_buf )
- {
- if ( TY_OSD_debug )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "(TY_OSD_debug) %s\n",
- TY_CC_buf );
- TY_CC_ptr = TY_CC_buf;
- memset(TY_CC_buf, 0, sizeof(TY_CC_buf));
- }
-
- if ( CC_mode != CURRENT ) return 0;
- }
-
- // preamble address code (row & indent)
- if ( b2 & 0x40 )
- {
- TY_CC_CUR_Y = CC_row[ ( ( b1 << 1 ) & 14 ) | ( ( b2 >> 5 ) & 1 ) ];
-
- // Offset into MPlayer's Buffer
- if ( ( TY_CC_CUR_Y >= 1 ) && ( TY_CC_CUR_Y <= 4 ) )
- {
- TY_CC_Y_Offset = SUB_MAX_TEXT - 5 - 1;
- }
- if ( ( TY_CC_CUR_Y >= 5 ) && ( TY_CC_CUR_Y <= 10 ) )
- {
- TY_CC_Y_Offset = SUB_MAX_TEXT - 5 - 5;
- }
- if ( ( TY_CC_CUR_Y >= 12 ) && ( TY_CC_CUR_Y <= 15 ) )
- {
- TY_CC_Y_Offset = SUB_MAX_TEXT - 5 - 12;
- }
-
- if ( TY_OSD_debug > 3 )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "<< preamble %d >>\n", TY_CC_CUR_Y );
-
- // we still have something in the text buffer
- if (TY_CC_ptr != TY_CC_buf)
- {
- *(TY_CC_ptr++) = '\n';
- if ( TY_CC_TextItalic )
- {
- TY_CC_TextItalic = 0;
- }
- }
-
- TY_CC_CUR_X = 1;
- // row contains indent flag
- if ( b2 & 0x10 )
- {
- for ( x = 0 ; x < ( ( b2 & 0x0F ) << 1 ) ; x++ )
- {
- TY_CC_CUR_X++;
- *(TY_CC_ptr++) = ' ';
- }
- }
- }
- else
- // !(b2 & 0x40)
- {
- if ( TY_OSD_debug > 3 )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "<< %02x >>\n", b1 & 0x7 );
- switch (b1 & 0x07)
- {
- case 0x00: // attribute
- {
- if ( TY_OSD_debug > 1 )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "<<A: %d>>\n", b2 );
- break;
- }
- case 0x01: // midrow or char
- {
- switch (b2 & 0x70)
- {
- case 0x20: // midrow attribute change
- {
- switch (b2 & 0x0e)
- {
- case 0x00: // italics off
- {
- TY_CC_TextItalic = 0;
- *(TY_CC_ptr++) = ' ';
- break;
- }
- case 0x0e: // italics on
- {
- ty_drawchar(' ');
- TY_CC_TextItalic = 1;
- break;
- }
- default:
- {
- if ( TY_OSD_debug > 1 )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "<<D: %d>>\n",
- b2 & 0x0e );
- }
- }
- if ( b2 & 0x01 )
- {
- // TextUnderline = 1;
- }
- else
- {
- // TextUnderline = 0;
- }
- break;
- }
- case 0x30: // special character..
- {
- // transparent space
- if ( ( b2 & 0x0f ) == 9 )
- {
- TY_CC_CUR_X++;
- *(TY_CC_ptr++) = ' ';
- }
- else
- {
- // ty_drawchar(specialchar[ b2 & 0x0f ] );
- ty_drawchar( ' ' );
- }
- break;
- }
- }
- break;
- }
-
- case 0x04: // misc
- case 0x05: // misc + F
- {
- if ( TY_OSD_debug > 3 )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "<< misc %02x >>\n", b2 );
- switch ( b2 )
- {
- case 0x20: // resume caption (new caption)
- {
- if ( TY_OSD_flags & TY_OSD_MODE &&
- TY_CC_stat != TY_CCPOPUP )
- ty_ClearOSD( 1 );
- TY_CC_stat = TY_CCPOPUP;
- break;
- }
-
- case 0x21: // backspace
- {
- TY_CC_CUR_X--;
- break;
- }
-
- case 0x25: // 2-4 row captions
- case 0x26:
- case 0x27:
- {
- if ( TY_CC_stat == TY_CCPOPUP ) ty_ClearOSD( 1 );
- TY_CC_stat = b2 - 0x23;
- if ( TY_CC_CUR_Y < TY_CC_stat ) TY_CC_CUR_Y = TY_CC_stat;
- break;
- }
-
- case 0x29: // resume direct caption
- {
- TY_CC_stat = TY_CCPAINTON;
- break;
- }
-
- case 0x2A: // text restart
- {
- ty_draw();
- /* FALL */
- }
-
- case 0x2B: // resume text display
- {
- TY_CC_stat = TY_CCTEXTMODE;
- break;
- }
-
- case 0x2C: // erase displayed memory
- {
- TY_CC_lastcap = 0;
- if ( TY_OSD_flags & TY_OSD_MODE )
- {
- if ( TY_CC_stat > TY_CCPOPUP || TY_CC_ptr == TY_CC_buf )
- {
- ty_ClearOSD( 1 );
- ty_draw();
- }
- else
- {
- ty_ClearOSD( 1 );
-
- // CRW -
- // new buffer
- // Used to be a buffer swap here, dunno why
- }
- }
- break;
- }
-
- case 0x2D: // carriage return
- {
- ty_draw();
- TY_CC_CUR_X = 1;
- if ( TY_OSD_flags & TY_OSD_MODE )
- {
- if ( TY_CC_stat > TY_CCPAINTON )
- ty_RollupBuf
- (
- TY_CC_CUR_Y - TY_CC_stat + 1 ,
- TY_CC_CUR_Y - TY_CC_stat + 2,
- TY_CC_stat - 1
- );
- else
- TY_CC_CUR_Y++;
- }
- break;
- }
-
- case 0x2F: // end caption + swap memory
- {
- ty_draw();
- /* FALL THROUGH TO 0x2E */
- }
-
- case 0x2E: // erase non-displayed memory
- {
- if ( TY_OSD_debug && TY_CC_ptr != TY_CC_buf )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "(TY_OSD_debug) %s\n",
- TY_CC_buf );
- if ( TY_OSD_flags & TY_OSD_MODE ) ty_ClearOSD( 1 );
-
- TY_CC_CUR_X = 1;
- TY_CC_CUR_Y = -1;
-
- TY_CC_ptr = TY_CC_buf;
- memset( TY_CC_buf, 0, sizeof( TY_CC_buf ) );
- }
- }
- break;
- }
- case 0x07: // misc (TAB)
- {
- for ( x = 0 ; x < ( b2 - 0x20 ) ; x++ )
- TY_CC_CUR_X++;
- break;
- }
- }
- }
- }
- CC_last = data;
- return 0;
-}
-
-// ===========================================================================
-// Extended Data Service Decoding and OSD Presentation
-// ===========================================================================
-#define XDS_BUFFER_LENGTH ( 16 )
-#define XDS_DISPLAY_FRAMES ( 120 )
-static char *ty_XDS_Display[ XDS_BUFFER_LENGTH ];
-static int ty_XDSAddLine = -1;
-static int ty_XDSDisplayCount = -1;
-
-
-static void ty_AddXDSToDisplay( const char *format, ... )
-{
- char line[ 80 ];
- int index;
- va_list ap;
-
- if ( ty_XDSAddLine == -1 )
- {
- for( index = 0 ; index < XDS_BUFFER_LENGTH ; index++ )
- {
- ty_XDS_Display[ index ] = 0;
- }
- ty_XDSAddLine = 0;
- }
-
- va_start( ap, format );
- vsnprintf( line, 80, format, ap );
- va_end( ap );
- mp_msg( MSGT_DEMUX, MSGL_V, "XDS: %s\n", line );
-
- if ( ty_XDSAddLine == XDS_BUFFER_LENGTH )
- {
- mp_msg( MSGT_DEMUX, MSGL_ERR, "XDS Buffer would have been blown\n" );
- }
-
- if ( ty_XDS_Display[ ty_XDSAddLine ] != 0 )
- {
- free( ty_XDS_Display[ ty_XDSAddLine ] );
- ty_XDS_Display[ ty_XDSAddLine ] = 0;
- }
-
- ty_XDS_Display[ ty_XDSAddLine ] = malloc( strlen( line ) + 1 );
- strcpy( ty_XDS_Display[ ty_XDSAddLine ], line );
- ty_XDSAddLine++;
-}
-
-
-static void ty_DisplayXDSInfo(void)
-{
- int index;
- int size;
-
- if ( ty_XDSDisplayCount == -1 )
- {
- for( index = 0 ; index < XDS_BUFFER_LENGTH ; index++ )
- {
- if ( ty_XDS_Display[ index ] != 0 )
- {
- break;
- }
- }
- if ( index != XDS_BUFFER_LENGTH )
- {
- size = strlen( ty_XDS_Display[ index ] );
-
- // Right Justify the XDS Stuff
- memcpy( &( ty_OSD1.text[ 0 ][ TY_CC_MAX_X - size - 1 ] ),
- ty_XDS_Display[ index ], size );
- free( ty_XDS_Display[ index ] );
- ty_XDS_Display[ index ] = 0;
- ty_XDSDisplayCount = 0;
- tyOSDUpdate = 1;
-
- }
- else
- {
- // We cleaned out all the XDS stuff to be displayed
- ty_XDSAddLine = 0;
- }
- }
- else
- {
- // We displayed that piece of XDS information long enough
- // Let's move on
- ty_XDSDisplayCount++;
- if ( ty_XDSDisplayCount >= XDS_DISPLAY_FRAMES )
- {
- memset( ty_OSD1.text[ 0 ], ' ', TY_CC_MAX_X - 1 );
- ty_OSD1.text[ 0 ][ TY_CC_MAX_X - 1 ] = 0;
- ty_XDSDisplayCount = -1;
- tyOSDUpdate = 1;
- }
- }
-}
-
-
-static int TY_XDS_mode = 0;
-static int TY_XDS_type = 0;
-static int TY_XDS_length = 0;
-static char TY_XDS_checksum = 0;
-
-// Array of [ Mode ][ Type ][ Length ]
-static char TY_XDS [ 8 ][ 25 ][ 34 ];
-static char TY_XDS_new[ 8 ][ 25 ][ 34 ];
-
-// Array of [ MPAARating|TVRating ][ NumberRatings ]
-static const char * const TY_XDS_CHIP[ 2 ][ 8 ] =
-{
- { "(NOT APPLICABLE)", "G", "PG", "PG-13", "R", "NC-17", "X", "(NOT RATED)" },
- { "(NOT RATED)", "TV-Y", "TV-Y7", "TV-G", "TV-PG", "TV-14", "TV-MA",
- "(NOT RATED)" }
-};
-
-static const char * const TY_XDS_modes[] =
-{
- "CURRENT", // 01h-02h current program
- "FUTURE ", // 03h-04h future program
- "CHANNEL", // 05h-06h channel
- "MISC. ", // 07h-08h miscellaneous
- "PUBLIC ", // 09h-0Ah public service
- "RESERV.", // 0Bh-0Ch reserved
- "UNDEF. ",
- "INVALID",
- "INVALID",
- "INVALID"
-};
-
-static int ty_XDSdecode( char b1, char b2 )
-{
- char line[ 80 ];
-
- if ( b1 < 0x0F )
- { // start packet
- TY_XDS_length = 0;
- TY_XDS_mode = b1 >> 1; // every other mode is a resume
- TY_XDS_type = b2;
- TY_XDS_checksum = b1 + b2;
- return 0;
- }
-
- TY_XDS_checksum += b1 + b2;
-
- // eof (next byte is checksum)
- if ( b1 == 0x0F )
- {
- // validity check
- if ( !TY_XDS_length || TY_XDS_checksum & 0x7F )
- {
- if ( TY_OSD_debug > 3 && !TY_XDS_length )
- {
- mp_msg( MSGT_DEMUX, MSGL_DBG3,
- "%% TY_XDS CHECKSUM ERROR (ignoring)\n" );
- }
- else
- {
- TY_XDS_mode = 0;
- TY_XDS_type = 0;
- return 1;
- }
- }
-
- // check to see if the data has changed.
- if ( strncmp( TY_XDS[ TY_XDS_mode ][ TY_XDS_type ],
- TY_XDS_new[ TY_XDS_mode ][ TY_XDS_type ], TY_XDS_length - 1 ) )
- {
- char *TY_XDS_ptr = TY_XDS[ TY_XDS_mode ][ TY_XDS_type ];
-
- TY_XDS_ptr[ TY_XDS_length ] = 0;
- memcpy( TY_XDS[ TY_XDS_mode ][ TY_XDS_type ],
- TY_XDS_new[ TY_XDS_mode ][ TY_XDS_type ], TY_XDS_length );
-
- // nasty hack: only print time codes if seconds are 0
- if ( TY_XDS_mode == 3 && TY_XDS_type == 1 &&
- !( TY_XDS_new[ 3 ][ 1 ][ 3 ] & 0x20 ) )
- {
- return 0;
- }
- if ( TY_XDS_mode == 0 && TY_XDS_type == 2 &&
- ( TY_XDS_new[ 0 ][ 2 ][ 4 ] & 0x3f ) > 1 )
- {
- return 0;
- }
-
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "%% %s ", TY_XDS_modes[ TY_XDS_mode ] );
-
- line[ 0 ] = 0;
- // printf( "XDS Code %x\n",
- // ( TY_XDS_mode << 9 ) + TY_XDS_type + 0x100 );
- switch ( ( TY_XDS_mode << 9 ) + TY_XDS_type + 0x100 )
- {
- // cases are specified in 2 bytes hex representing mode, type.
- // TY_XDS_ptr will point to the current class buffer
- case 0x0101: // current
- case 0x0301: // future
- {
- char *mon[] =
- {
- "0", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
- "Aug", "Sep", "Oct", "Nov", "Dec", "13", "14", "15"
- };
- ty_AddXDSToDisplay( "AIR DATE: %s %2d %d:%02d:00",
- mon[ TY_XDS_ptr[ 3 ] & 0x0f ],
- TY_XDS_ptr[ 2 ] & 0x1f,
- TY_XDS_ptr[ 1 ] & 0x1f,
- TY_XDS_ptr[ 0 ] & 0x3f
- );
-
- // Program is tape delayed
- if ( TY_XDS_ptr[ 3 ] & 0x10 ) ty_AddXDSToDisplay( " TAPE" );
- }
- break;
-
- case 0x0102: // current program length
- case 0x0302: // future
- {
- ty_AddXDSToDisplay(
- "DURATION: %d:%02d:%02d of %d:%02d:%02d",
- TY_XDS_ptr[ 3 ] & 0x3f,
- TY_XDS_ptr[ 2 ] & 0x3f,
- TY_XDS_ptr[ 4 ] & 0x3f,
- TY_XDS_ptr[ 1 ] & 0x3f,
- TY_XDS_ptr[ 0 ] & 0x3f, 0);
- break;
- }
-
- case 0x0103: // current program name
- case 0x0303: // future
- {
- ty_AddXDSToDisplay( "TITLE: %s", TY_XDS_ptr );
- break;
- }
-
- case 0x0104: // current program type
- case 0x0304: // future
- {
- // for now just print out the raw data
- // requires a 127 string array to parse
- // properly and isn't worth it.
- sprintf ( line, "%sGENRE:", line );
- {
- int x;
- for ( x = 0 ; x < TY_XDS_length ; x++ )
- sprintf( line, "%s %02x", line, TY_XDS_ptr[ x ] );
- }
- ty_AddXDSToDisplay( line );
- break;
- }
-
- case 0x0105: // current program rating
- case 0x0305: // future
- {
- sprintf( line, "%sRATING: %s", line,
- TY_XDS_CHIP[ ( TY_XDS_ptr[ 0 ] & 0x08 ) >> 3 ]
- [ TY_XDS_ptr[ 1 ] & 0x07 ] );
- if ( TY_XDS_ptr[ 0 ] & 0x20 )
- sprintf( line, "%s DIALOGUE", line );
- if ( TY_XDS_ptr[ 1 ] & 0x08 )
- sprintf( line, "%s LANGUAGE", line );
- if ( TY_XDS_ptr[ 1 ] & 0x10 )
- sprintf( line, "%s SEXUAL", line );
- if ( TY_XDS_ptr[ 1 ] & 0x20 )
- sprintf( line, "%s VIOLENCE", line );
- ty_AddXDSToDisplay( line );
-
- // raw output for verification.
- if ( TY_OSD_debug > 1 )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, " (%02x %02x)",
- TY_XDS_ptr[ 0 ], TY_XDS_ptr[ 1 ] );
- break;
- }
-
- case 0x0106: // current program audio services
- case 0x0306: // future
- {
- // requires table, never actually seen it used either
- ty_AddXDSToDisplay( "AUDIO: %02x %02x", TY_XDS_ptr[ 0 ],
- TY_XDS_ptr[ 1 ] );
- break;
- }
-
- case 0x0109: // current program aspect ratio
- case 0x0309: // future
- {
- // requires table, rare
- ty_AddXDSToDisplay( "ASPECT: %02x %02x",
- TY_XDS_ptr[ 0 ], TY_XDS_ptr[ 1 ] );
- break;
- }
-
- case 0x0110: // program description
- case 0x0111:
- case 0x0112:
- case 0x0113:
- case 0x0114:
- case 0x0115:
- case 0x0116:
- case 0x0117:
- {
- ty_AddXDSToDisplay( "DESCRIP: %s", TY_XDS_ptr );
- break;
- }
-
- case 0x0501: // channel network name
- {
- ty_AddXDSToDisplay( "NETWORK: %s", TY_XDS_ptr );
- break;
- }
-
- case 0x0502: // channel network call letters
- {
- ty_AddXDSToDisplay( "CALLSIGN: %s", TY_XDS_ptr );
- break;
- }
-
- case 0x0701: // misc. time of day
- {
-#define TIMEZONE ( TY_XDS[ 3 ][ 4 ][ 0 ] & 0x1f )
-#define DST ( ( TY_XDS[ 3 ][ 4 ][ 0 ] & 0x20 ) >> 5 )
- struct tm tm =
- {
- .tm_sec = 0, // sec
- .tm_min = ( TY_XDS_ptr[ 0 ] & 0x3F ), // min
- .tm_hour = ( TY_XDS_ptr[ 1 ] & 0x1F ), // hour
- .tm_mday = ( TY_XDS_ptr[ 2 ] & 0x1F ), // day
- .tm_mon = ( TY_XDS_ptr[ 3 ] & 0x1f ) - 1, // month
- .tm_year = ( TY_XDS_ptr[ 5 ] & 0x3f ) + 90, // year
- .tm_wday = 0, // day of week
- .tm_yday = 0, // day of year
- .tm_isdst = 0, // DST
- };
-
- time_t time_t = mktime( &tm );
- char *timestr;
-
- time_t -= ( ( TIMEZONE - DST ) * 60 * 60 );
- timestr = ctime( &time_t );
- timestr[ strlen( timestr ) - 1 ] = 0;
-
- sprintf( line, "%sCUR.TIME: %s ", line, timestr );
- if ( TY_XDS[ 3 ][ 4 ][ 0 ] )
- {
- sprintf( line, "%sUTC-%d", line, TIMEZONE );
- if (DST) sprintf( line, "%s DST", line );
- }
- else
- sprintf( line, "%sUTC", line );
-
- ty_AddXDSToDisplay( line );
-
- break;
- }
-
- case 0x0704: //misc. local time zone
- {
- sprintf( line, "%sTIMEZONE: UTC-%d",
- line, TY_XDS_ptr[ 0 ] & 0x1f );
- if ( TY_XDS_ptr[ 0 ] & 0x20 ) sprintf( line, "%s DST", line );
- ty_AddXDSToDisplay( line );
- break;
- }
-
- default:
- {
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "UNKNOWN CLASS %d TYPE %d",
- ( TY_XDS_mode << 1 ) + 1, TY_XDS_type );
- if ( TY_OSD_debug > 1 )
- {
- int x;
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "\nDUMP:\n" );
- for ( x = 0 ; x < TY_XDS_length ; x++ )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, " %02x %c",
- TY_XDS_ptr[ x ], TY_XDS_ptr[ x ] );
- mp_msg( MSGT_DEMUX, MSGL_DBG3, "\n" );
- }
- }
- }
- if ( TY_OSD_debug > 1 )
- mp_msg( MSGT_DEMUX, MSGL_DBG3, " (%d)", TY_XDS_length );
- }
- TY_XDS_mode = 0;
- TY_XDS_type = 0;
- }
- else if ( TY_XDS_length < 34 )
- {
- TY_XDS_new[ TY_XDS_mode ][ TY_XDS_type ][ TY_XDS_length++ ] = b1;
- TY_XDS_new[ TY_XDS_mode ][ TY_XDS_type ][ TY_XDS_length++ ] = b2;
- }
- return 0;
-}
-
-
-// ===========================================================================
-// Callback from Video Display Processing to put up the OSD
-// ===========================================================================
-void ty_processuserdata( const unsigned char* buf, int len )
-{
- int index;
-
- sub_justify = 1;
-
- if ( subcc_enabled )
- {
- if ( tyOSDInitialized == 0 )
- {
- for ( index = 0; index < SUB_MAX_TEXT ; index++ )
- {
- ty_OSD1.text[ index ] = malloc( TY_CC_MAX_X );
- ty_OSD2.text[ index ] = malloc( TY_CC_MAX_X );
- }
- ty_ClearOSD( 0 );
- ty_OSD1.lines = SUB_MAX_TEXT;
- ty_OSD2.lines = SUB_MAX_TEXT;
- ty_pOSD1 = &ty_OSD1;
- ty_pOSD2 = &ty_OSD2;
- tyOSDUpdate = 0;
- tyOSDInitialized = 1;
- }
-
- if ( buf[ 0 ] == 0x01 )
- {
- ty_CCdecode( buf[ 1 ], buf[ 2 ] );
- }
- if ( buf[ 0 ] == 0x02 )
- {
- ty_XDSdecode( buf[ 1 ], buf[ 2 ] );
- }
-
- ty_DisplayXDSInfo();
-
- if ( tyOSDUpdate )
- {
- // for ( index = 0; index < SUB_MAX_TEXT ; index++ )
- // {
- // printf( "OSD:%d:%s\n", index, ty_OSD1.text[ index ] );
- // }
- vo_sub = &ty_OSD1;
- vo_osd_changed( OSDTYPE_SUBTITLE );
- tyOSDUpdate = 0;
- }
- }
-}
diff --git a/libmpdemux/demux_ty_osd.h b/libmpdemux/demux_ty_osd.h
deleted file mode 100644
index ce0af05788..0000000000
--- a/libmpdemux/demux_ty_osd.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_DEMUX_TY_OSD_H
-#define MPLAYER_DEMUX_TY_OSD_H
-
-void ty_ClearOSD(int start);
-void ty_processuserdata(const unsigned char *buf, int len);
-
-#endif /* MPLAYER_DEMUX_TY_OSD_H */
diff --git a/libmpdemux/demux_vqf.c b/libmpdemux/demux_vqf.c
deleted file mode 100644
index 051e912339..0000000000
--- a/libmpdemux/demux_vqf.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <libavutil/common.h>
-#include <libavutil/intreadwrite.h>
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-#include "libmpcodecs/vqf.h"
-
-static int demux_probe_vqf(demuxer_t* demuxer)
-{
- char buf[KEYWORD_BYTES];
- stream_t *s;
- s = demuxer->stream;
- if(stream_read(s,buf,KEYWORD_BYTES)!=KEYWORD_BYTES)
- return 0;
- if(memcmp(buf,"TWIN",KEYWORD_BYTES)==0) return DEMUXER_TYPE_VQF; /*version: 97012000*/
- return 0;
-}
-
-static demuxer_t* demux_open_vqf(demuxer_t* demuxer) {
- sh_audio_t* sh_audio;
- WAVEFORMATEX* w;
- stream_t *s;
- headerInfo *hi;
-
- s = demuxer->stream;
-
- sh_audio = new_sh_audio(demuxer,0);
- sh_audio->wf = w = calloc(1, sizeof(*sh_audio->wf)+sizeof(headerInfo));
- hi = (headerInfo *)&w[1];
- w->wFormatTag = 0x1;
- sh_audio->format = mmioFOURCC('T','W','I','N'); /* TWinVQ */
- w->nChannels = sh_audio->channels = 2;
- w->nSamplesPerSec = sh_audio->samplerate = 44100;
- w->nAvgBytesPerSec = w->nSamplesPerSec*sh_audio->channels*2;
- w->nBlockAlign = 0;
- sh_audio->samplesize = 2;
- w->wBitsPerSample = 8*sh_audio->samplesize;
- w->cbSize = 0;
- strcpy(hi->ID,"TWIN");
- stream_read(s,hi->ID+KEYWORD_BYTES,VERSION_BYTES); /* fourcc+version_id */
- while(1)
- {
- char chunk_id[4];
- unsigned chunk_size;
- hi->size=chunk_size=stream_read_dword(s); /* include itself */
- stream_read(s,chunk_id,4);
- if (chunk_size < 8) return NULL;
- chunk_size -= 8;
- if(AV_RL32(chunk_id)==mmioFOURCC('C','O','M','M'))
- {
- char buf[BUFSIZ];
- unsigned i,subchunk_size;
- if (chunk_size > sizeof(buf) || chunk_size < 20) return NULL;
- if(stream_read(s,buf,chunk_size)!=chunk_size) return NULL;
- i=0;
- subchunk_size = AV_RB32(buf);
- hi->channelMode = AV_RB32(buf + 4);
- w->nChannels=sh_audio->channels=hi->channelMode+1; /*0-mono;1-stereo*/
- hi->bitRate = AV_RB32(buf + 8);
- sh_audio->i_bps=hi->bitRate*1000/8; /* bitrate kbit/s */
- w->nAvgBytesPerSec = sh_audio->i_bps;
- hi->samplingRate = AV_RB32(buf + 12);
- switch(hi->samplingRate){
- case 44:
- w->nSamplesPerSec=44100;
- break;
- case 22:
- w->nSamplesPerSec=22050;
- break;
- case 11:
- w->nSamplesPerSec=11025;
- break;
- default:
- w->nSamplesPerSec=hi->samplingRate*1000;
- break;
- }
- sh_audio->samplerate=w->nSamplesPerSec;
- hi->securityLevel = AV_RB32(buf + 16);
- w->nBlockAlign = 0;
- sh_audio->samplesize = 4;
- w->wBitsPerSample = 8*sh_audio->samplesize;
- w->cbSize = 0;
- if (subchunk_size > chunk_size - 4) continue;
- i+=subchunk_size+4;
- while(i + 8 < chunk_size)
- {
- unsigned slen,sid;
- char sdata[BUFSIZ];
- sid = AV_RL32(buf + i); i+=4;
- slen = AV_RB32(buf + i); i+=4;
- if (slen > sizeof(sdata) - 1 || slen > chunk_size - i) break;
- if(sid==mmioFOURCC('D','S','I','Z'))
- {
- hi->Dsiz=AV_RB32(buf + i);
- continue; /* describes the same info as size of DATA chunk */
- }
- memcpy(sdata,&buf[i],slen); sdata[slen]=0; i+=slen;
- if(sid==mmioFOURCC('N','A','M','E'))
- {
- memcpy(hi->Name,sdata,FFMIN(BUFSIZ,slen));
- demux_info_add(demuxer,"Title",sdata);
- }
- else
- if(sid==mmioFOURCC('A','U','T','H'))
- {
- memcpy(hi->Auth,sdata,FFMIN(BUFSIZ,slen));
- demux_info_add(demuxer,"Author",sdata);
- }
- else
- if(sid==mmioFOURCC('C','O','M','T'))
- {
- memcpy(hi->Comt,sdata,FFMIN(BUFSIZ,slen));
- demux_info_add(demuxer,"Comment",sdata);
- }
- else
- if(sid==mmioFOURCC('(','c',')',' '))
- {
- memcpy(hi->Cpyr,sdata,FFMIN(BUFSIZ,slen));
- demux_info_add(demuxer,"Copyright",sdata);
- }
- else
- if(sid==mmioFOURCC('F','I','L','E'))
- {
- memcpy(hi->File,sdata,FFMIN(BUFSIZ,slen));
- }
- else
- if(sid==mmioFOURCC('A','L','B','M')) demux_info_add(demuxer,"Album",sdata);
- else
- if(sid==mmioFOURCC('Y','E','A','R')) demux_info_add(demuxer,"Date",sdata);
- else
- if(sid==mmioFOURCC('T','R','A','C')) demux_info_add(demuxer,"Track",sdata);
- else
- if(sid==mmioFOURCC('E','N','C','D')) demux_info_add(demuxer,"Encoder",sdata);
- else
- mp_msg(MSGT_DEMUX, MSGL_V, "Unhandled subchunk '%c%c%c%c'='%s'\n",((char *)&sid)[0],((char *)&sid)[1],((char *)&sid)[2],((char *)&sid)[3],sdata);
- /* rest not recognized due to untranslatable Japanese expressions */
- }
- }
- else
- if(AV_RL32(chunk_id)==mmioFOURCC('D','A','T','A'))
- {
- demuxer->movi_start=stream_tell(s);
- demuxer->movi_end=demuxer->movi_start+chunk_size;
- mp_msg(MSGT_DEMUX, MSGL_V, "Found data at %"PRIX64" size %"PRIu64"\n",demuxer->movi_start,demuxer->movi_end);
- /* Done! play it */
- break;
- }
- else
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "Unhandled chunk '%c%c%c%c' %u bytes\n",chunk_id[0],chunk_id[1],chunk_id[2],chunk_id[3],chunk_size);
- stream_skip(s,chunk_size); /*unknown chunk type */
- }
- }
-
- demuxer->audio->id = 0;
- demuxer->audio->sh = sh_audio;
- sh_audio->ds = demuxer->audio;
- stream_seek(s,demuxer->movi_start);
- demuxer->seekable=0;
- return demuxer;
-}
-
-static int demux_vqf_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) {
- sh_audio_t* sh_audio = demuxer->audio->sh;
- int l = sh_audio->wf->nAvgBytesPerSec;
- off_t spos = stream_tell(demuxer->stream);
- demux_packet_t* dp;
-
- if(stream_eof(demuxer->stream))
- return 0;
-
- dp = new_demux_packet(l);
- ds->pts = spos / (float)(sh_audio->wf->nAvgBytesPerSec);
- ds->pos = spos;
-
- l=stream_read(demuxer->stream,dp->buffer,l);
- resize_demux_packet(dp,l);
- ds_add_packet(ds,dp);
-
- return 1;
-}
-
-static void demux_seek_vqf(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
-#if 0
- stream_t* s = demuxer->stream;
- sh_audio_t* sh_audio = demuxer->audio->sh;
- off_t base,pos;
-
- base = (flags & SEEK_ABSOLUTE) ? demuxer->movi_start : stream_tell(s);
- if(flags & SEEK_FACTOR)
- pos = base + ((demuxer->movi_end - demuxer->movi_start)*rel_seek_secs);
- else
- pos = base + (rel_seek_secs*sh_audio->i_bps);
-
- pos -= (pos % (sh_audio->channels * sh_audio->samplesize) );
- stream_seek(s,pos);
-#endif
-}
-
-static void demux_close_vqf(demuxer_t* demuxer) {}
-
-
-const demuxer_desc_t demuxer_desc_vqf = {
- "TwinVQ demuxer",
- "vqf",
- "VQF",
- "Nick Kurshev",
- "ported from MPlayerXP",
- DEMUXER_TYPE_VQF,
- 1, // safe autodetect
- demux_probe_vqf,
- demux_vqf_fill_buffer,
- demux_open_vqf,
- demux_close_vqf,
- demux_seek_vqf,
- NULL
-};
diff --git a/libmpdemux/demux_y4m.c b/libmpdemux/demux_y4m.c
deleted file mode 100644
index cf0f7cf7e6..0000000000
--- a/libmpdemux/demux_y4m.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Y4M file parser
- * copyright (c) 2001 Rik Snel
- * (using yuv4mpeg*.[ch] from mjpeg.sourceforge.net)
- * (derived from demux_viv.c)
- * older YUV4MPEG (used by xawtv) support by Alex Beregszaszi
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h> /* strtok */
-
-#include "config.h"
-#include "mp_msg.h"
-#include "yuv4mpeg.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-
-typedef struct {
- int framenum;
- y4m_stream_info_t* si;
- int is_older;
-} y4m_priv_t;
-
-static int y4m_check_file(demuxer_t* demuxer){
- int orig_pos = stream_tell(demuxer->stream);
- char buf[10];
- y4m_priv_t* priv;
-
- mp_msg(MSGT_DEMUX, MSGL_V, "Checking for YUV4MPEG2\n");
-
- if(stream_read(demuxer->stream, buf, 9)!=9)
- return 0;
-
- buf[9] = 0;
-
- if (strncmp("YUV4MPEG2", buf, 9) && strncmp("YUV4MPEG ", buf, 9)) {
- return 0;
- }
-
- demuxer->priv = malloc(sizeof(y4m_priv_t));
- priv = demuxer->priv;
-
- priv->is_older = 0;
-
- if (!strncmp("YUV4MPEG ", buf, 9))
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "Found older YUV4MPEG format (used by xawtv)\n");
- priv->is_older = 1;
- }
-
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"Success: YUV4MPEG2\n");
-
- stream_seek(demuxer->stream, orig_pos);
-
- return DEMUXER_TYPE_Y4M;
-}
-
-static void read_streaminfo(demuxer_t *demuxer);
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_y4m_fill_buffer(demuxer_t *demux, demux_stream_t *dsds) {
- demux_stream_t *ds=demux->video;
- demux_packet_t *dp;
- y4m_priv_t *priv=demux->priv;
- y4m_frame_info_t fi;
- unsigned char *buf[3];
- int err, size;
- int nextc;
-
- // Concatenated stream check; only done if seekable so skip(-1) works
- if (demux->stream->flags & MP_STREAM_SEEK_BW) {
- nextc = stream_read_char(demux->stream);
- stream_skip(demux->stream, -1);
- if (nextc == 'Y') {
- read_streaminfo(demux);
- demux->seekable = 0;
- }
- }
-
- y4m_init_frame_info(&fi);
-
- demux->filepos=stream_tell(demux->stream);
-
- size = ((sh_video_t*)ds->sh)->disp_w*((sh_video_t*)ds->sh)->disp_h;
-
- dp = new_demux_packet(3*size/2);
-
- /* swap U and V components */
- buf[0] = dp->buffer;
- buf[1] = dp->buffer + 5*size/4;
- buf[2] = dp->buffer + size;
-
- if (priv->is_older)
- {
- int c;
-
- c = stream_read_char(demux->stream); /* F */
- if (c == -256)
- return 0; /* EOF */
- if (c != 'F')
- {
- mp_msg(MSGT_DEMUX, MSGL_V, "Bad frame at %d\n", (int)stream_tell(demux->stream)-1);
- return 0;
- }
- stream_skip(demux->stream, 5); /* RAME\n */
- stream_read(demux->stream, buf[0], size);
- stream_read(demux->stream, buf[1], size/4);
- stream_read(demux->stream, buf[2], size/4);
- }
- else
- {
- if ((err=y4m_read_frame(demux->stream, priv->si, &fi, buf)) != Y4M_OK) {
- mp_msg(MSGT_DEMUX, MSGL_ERR, "error reading frame %s\n", y4m_strerr(err));
- return 0;
- }
- }
-
- /* This seems to be the right way to calculate the presentation time stamp */
- dp->pts=(float)priv->framenum/((sh_video_t*)ds->sh)->fps;
- priv->framenum++;
- dp->pos=demux->filepos;
- ds_add_packet(ds, dp);
-
- return 1;
-}
-
-static void read_streaminfo(demuxer_t *demuxer)
-{
- y4m_priv_t *priv = demuxer->priv;
- sh_video_t *sh = demuxer->video->sh;
- y4m_ratio_t ratio;
- int err;
-
- if (priv->is_older)
- {
- char buf[4];
- int frame_rate_code;
-
- stream_skip(demuxer->stream, 8); /* YUV4MPEG */
- stream_skip(demuxer->stream, 1); /* space */
- stream_read(demuxer->stream, (char *)&buf[0], 3);
- buf[3] = 0;
- sh->disp_w = atoi(buf);
- stream_skip(demuxer->stream, 1); /* space */
- stream_read(demuxer->stream, (char *)&buf[0], 3);
- buf[3] = 0;
- sh->disp_h = atoi(buf);
- stream_skip(demuxer->stream, 1); /* space */
- stream_read(demuxer->stream, (char *)&buf[0], 1);
- buf[1] = 0;
- frame_rate_code = atoi(buf);
- stream_skip(demuxer->stream, 1); /* new-line */
-
- if (!sh->fps)
- {
- /* values from xawtv */
- switch(frame_rate_code)
- {
- case 1:
- sh->fps = 23.976f;
- break;
- case 2:
- sh->fps = 24.0f;
- break;
- case 3:
- sh->fps = 25.0f;
- break;
- case 4:
- sh->fps = 29.97f;
- break;
- case 5:
- sh->fps = 30.0f;
- break;
- case 6:
- sh->fps = 50.0f;
- break;
- case 7:
- sh->fps = 59.94f;
- break;
- case 8:
- sh->fps = 60.0f;
- break;
- default:
- sh->fps = 25.0f;
- }
- }
- sh->frametime = 1.0f/sh->fps;
- }
- else
- {
- y4m_init_stream_info(priv->si);
- if ((err=y4m_read_stream_header(demuxer->stream, priv->si)) != Y4M_OK)
- mp_msg(MSGT_DEMUXER, MSGL_FATAL, "error parsing YUV4MPEG header: %s\n", y4m_strerr(err));
-
- if(!sh->fps) {
- ratio = y4m_si_get_framerate(priv->si);
- if (ratio.d != 0)
- sh->fps=(float)ratio.n/(float)ratio.d;
- else
- sh->fps=15.0f;
- }
- sh->frametime=1.0f/sh->fps;
-
- ratio = y4m_si_get_sampleaspect(priv->si);
-
- sh->disp_w = y4m_si_get_width(priv->si);
- sh->disp_h = y4m_si_get_height(priv->si);
-
- if (ratio.d != 0 && ratio.n != 0)
- sh->aspect = (float)(sh->disp_w*ratio.n)/(float)(sh->disp_h*ratio.d);
-
- demuxer->seekable = 0;
- }
-
- sh->format = mmioFOURCC('Y', 'V', '1', '2');
-
- sh->bih->biSize=40;
- sh->bih->biWidth = sh->disp_w;
- sh->bih->biHeight = sh->disp_h;
- sh->bih->biPlanes=3;
- sh->bih->biBitCount=12;
- sh->bih->biCompression=sh->format;
- sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight*3/2; /* YV12 */
-
- mp_msg(MSGT_DEMUX, MSGL_INFO, "YUV4MPEG2 Video stream %d size: display: %dx%d, codec: %ux%u\n",
- demuxer->video->id, sh->disp_w, sh->disp_h, sh->bih->biWidth,
- sh->bih->biHeight);
-}
-
-static demuxer_t* demux_open_y4m(demuxer_t* demuxer){
- y4m_priv_t* priv = demuxer->priv;
- sh_video_t* sh=new_sh_video(demuxer,0);
-
- priv->framenum = 0;
- priv->si = malloc(sizeof(y4m_stream_info_t));
-
- sh->bih=calloc(1, sizeof(*sh->bih));
-
- demuxer->video->sh=sh;
- sh->ds=demuxer->video;
- demuxer->video->id=0;
-
- read_streaminfo(demuxer);
-
- return demuxer;
-}
-
-static void demux_seek_y4m(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) {
- sh_video_t* sh = demuxer->video->sh;
- y4m_priv_t* priv = demuxer->priv;
- int rel_seek_frames = sh->fps*rel_seek_secs;
- int size = 3*sh->disp_w*sh->disp_h/2;
- off_t curr_pos = stream_tell(demuxer->stream);
-
- if (priv->framenum + rel_seek_frames < 0) rel_seek_frames = -priv->framenum;
-
- //printf("seektoframe=%d rel_seek_secs=%f seektooffset=%ld\n", priv->framenum + rel_seek_frames, rel_seek_secs, curr_pos + rel_seek_frames*(size+6));
- //printf("framenum=%d, curr_pos=%ld, currpos/(size+6)=%f\n", priv->framenum, curr_pos, (float)curr_pos/(float)(size+6));
- priv->framenum += rel_seek_frames;
-
- if (priv->is_older) {
- /* Well this is easy: every frame takes up size+6 bytes
- * in the stream and we may assume that the stream pointer
- * is always at the beginning of a frame.
- * framenum is the number of the frame that is about to be
- * demuxed (counting from ONE (see demux_open_y4m)) */
- stream_seek(demuxer->stream, curr_pos + rel_seek_frames*(size+6));
- } else {
- /* should never come here, because seeking for YUV4MPEG2
- * is disabled. */
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Seeking for YUV4MPEG2 not yet implemented!\n");
- }
-}
-
-static void demux_close_y4m(demuxer_t *demuxer)
-{
- y4m_priv_t* priv = demuxer->priv;
-
- if(!priv)
- return;
- if (!priv->is_older)
- y4m_fini_stream_info(((y4m_priv_t*)demuxer->priv)->si);
- free(((y4m_priv_t*)demuxer->priv)->si);
- free(demuxer->priv);
- return;
-}
-
-
-const demuxer_desc_t demuxer_desc_y4m = {
- "YUV4MPEG2 demuxer",
- "y4m",
- "YUV4MPEG2",
- "Rik snel",
- "",
- DEMUXER_TYPE_Y4M,
- 1, // safe autodetect
- y4m_check_file,
- demux_y4m_fill_buffer,
- demux_open_y4m,
- demux_close_y4m,
- demux_seek_y4m,
- NULL
-};
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index 0cce5e8543..e77e32b942 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -58,41 +58,19 @@ extern const demuxer_desc_t demuxer_desc_rawvideo;
extern const demuxer_desc_t demuxer_desc_tv;
extern const demuxer_desc_t demuxer_desc_mf;
extern const demuxer_desc_t demuxer_desc_avi;
-extern const demuxer_desc_t demuxer_desc_y4m;
extern const demuxer_desc_t demuxer_desc_asf;
extern const demuxer_desc_t demuxer_desc_real;
-extern const demuxer_desc_t demuxer_desc_smjpeg;
extern const demuxer_desc_t demuxer_desc_matroska;
extern const demuxer_desc_t demuxer_desc_realaudio;
-extern const demuxer_desc_t demuxer_desc_vqf;
-extern const demuxer_desc_t demuxer_desc_mov;
extern const demuxer_desc_t demuxer_desc_vivo;
-extern const demuxer_desc_t demuxer_desc_fli;
-extern const demuxer_desc_t demuxer_desc_film;
-extern const demuxer_desc_t demuxer_desc_roq;
extern const demuxer_desc_t demuxer_desc_gif;
-extern const demuxer_desc_t demuxer_desc_ogg;
extern const demuxer_desc_t demuxer_desc_avs;
-extern const demuxer_desc_t demuxer_desc_pva;
-extern const demuxer_desc_t demuxer_desc_nsv;
-extern const demuxer_desc_t demuxer_desc_mpeg_ts;
-extern const demuxer_desc_t demuxer_desc_lmlm4;
-extern const demuxer_desc_t demuxer_desc_mpeg_ps;
-extern const demuxer_desc_t demuxer_desc_mpeg_pes;
-extern const demuxer_desc_t demuxer_desc_mpeg_es;
-extern const demuxer_desc_t demuxer_desc_mpeg_gxf;
-extern const demuxer_desc_t demuxer_desc_mpeg4_es;
-extern const demuxer_desc_t demuxer_desc_h264_es;
extern const demuxer_desc_t demuxer_desc_rawdv;
-extern const demuxer_desc_t demuxer_desc_mpc;
extern const demuxer_desc_t demuxer_desc_audio;
-extern const demuxer_desc_t demuxer_desc_mpeg_ty;
extern const demuxer_desc_t demuxer_desc_rtp;
extern const demuxer_desc_t demuxer_desc_rtp_nemesi;
extern const demuxer_desc_t demuxer_desc_lavf;
extern const demuxer_desc_t demuxer_desc_lavf_preferred;
-extern const demuxer_desc_t demuxer_desc_aac;
-extern const demuxer_desc_t demuxer_desc_nut;
extern const demuxer_desc_t demuxer_desc_mng;
/* Please do not add any new demuxers here. If you want to implement a new
@@ -110,39 +88,16 @@ const demuxer_desc_t *const demuxer_list[] = {
&demuxer_desc_mf,
&demuxer_desc_lavf_preferred,
&demuxer_desc_avi,
- &demuxer_desc_y4m,
&demuxer_desc_asf,
- &demuxer_desc_nsv,
- &demuxer_desc_real,
- &demuxer_desc_smjpeg,
&demuxer_desc_matroska,
&demuxer_desc_realaudio,
- &demuxer_desc_vqf,
- &demuxer_desc_mov,
- &demuxer_desc_vivo,
- &demuxer_desc_fli,
- &demuxer_desc_film,
- &demuxer_desc_roq,
#ifdef CONFIG_GIF
&demuxer_desc_gif,
#endif
-#ifdef CONFIG_OGGVORBIS
- &demuxer_desc_ogg,
-#endif
#ifdef CONFIG_WIN32DLL
&demuxer_desc_avs,
#endif
- &demuxer_desc_pva,
- &demuxer_desc_mpeg_ts,
- &demuxer_desc_lmlm4,
- &demuxer_desc_mpeg_ps,
- &demuxer_desc_mpeg_pes,
- &demuxer_desc_mpeg_es,
- &demuxer_desc_mpeg_gxf,
- &demuxer_desc_mpeg4_es,
- &demuxer_desc_h264_es,
&demuxer_desc_audio,
- &demuxer_desc_mpeg_ty,
#ifdef CONFIG_LIVE555
&demuxer_desc_rtp,
#endif
@@ -150,16 +105,9 @@ const demuxer_desc_t *const demuxer_list[] = {
&demuxer_desc_rtp_nemesi,
#endif
&demuxer_desc_lavf,
-#ifdef CONFIG_MUSEPACK
- &demuxer_desc_mpc,
-#endif
#ifdef CONFIG_LIBDV095
&demuxer_desc_rawdv,
#endif
- &demuxer_desc_aac,
-#ifdef CONFIG_LIBNUT
- &demuxer_desc_nut,
-#endif
#ifdef CONFIG_MNG
&demuxer_desc_mng,
#endif
@@ -1002,6 +950,22 @@ static struct demuxer *demux_open_stream(struct MPOpts *opts,
struct demuxer *demuxer = NULL;
const struct demuxer_desc *desc;
+ // Some code (e.g. dvd stuff, network code, or extension.c) explicitly
+ // request certain file formats. The list of formats are always handled by
+ // libavformat.
+ // Maybe attempts should be made to convert the mplayer format to the libav
+ // format, instead of reyling on libav to auto-detect the stream's format
+ // correctly.
+ switch (file_format) {
+ case DEMUXER_TYPE_MPEG_PS:
+ case DEMUXER_TYPE_MPEG_TS:
+ case DEMUXER_TYPE_Y4M:
+ case DEMUXER_TYPE_NSV:
+ case DEMUXER_TYPE_AAC:
+ case DEMUXER_TYPE_MPC:
+ file_format = DEMUXER_TYPE_LAVF;
+ }
+
// If somebody requested a demuxer check it
if (file_format) {
desc = get_demuxer_desc_from_type(file_format);
diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h
index 3f9aa80b96..0e208d666e 100644
--- a/libmpdemux/demuxer.h
+++ b/libmpdemux/demuxer.h
@@ -44,47 +44,30 @@ struct MPOpts;
enum demuxer_type {
DEMUXER_TYPE_UNKNOWN = 0,
- DEMUXER_TYPE_MPEG_ES,
DEMUXER_TYPE_MPEG_PS,
DEMUXER_TYPE_AVI,
DEMUXER_TYPE_AVI_NI,
DEMUXER_TYPE_AVI_NINI,
DEMUXER_TYPE_ASF,
- DEMUXER_TYPE_MOV,
DEMUXER_TYPE_VIVO,
DEMUXER_TYPE_TV,
- DEMUXER_TYPE_FLI,
DEMUXER_TYPE_REAL,
DEMUXER_TYPE_Y4M,
- DEMUXER_TYPE_FILM,
- DEMUXER_TYPE_ROQ,
DEMUXER_TYPE_MF,
DEMUXER_TYPE_AUDIO,
- DEMUXER_TYPE_OGG,
DEMUXER_TYPE_RAWAUDIO,
DEMUXER_TYPE_RTP,
DEMUXER_TYPE_RAWDV,
- DEMUXER_TYPE_PVA,
- DEMUXER_TYPE_SMJPEG,
- DEMUXER_TYPE_XMMS,
DEMUXER_TYPE_RAWVIDEO,
- DEMUXER_TYPE_MPEG4_ES,
DEMUXER_TYPE_GIF,
DEMUXER_TYPE_MPEG_TS,
- DEMUXER_TYPE_H264_ES,
DEMUXER_TYPE_MATROSKA,
DEMUXER_TYPE_REALAUDIO,
- DEMUXER_TYPE_MPEG_TY,
- DEMUXER_TYPE_LMLM4,
DEMUXER_TYPE_LAVF,
DEMUXER_TYPE_NSV,
- DEMUXER_TYPE_VQF,
DEMUXER_TYPE_AVS,
DEMUXER_TYPE_AAC,
DEMUXER_TYPE_MPC,
- DEMUXER_TYPE_MPEG_PES,
- DEMUXER_TYPE_MPEG_GXF,
- DEMUXER_TYPE_NUT,
DEMUXER_TYPE_LAVF_PREFERRED,
DEMUXER_TYPE_RTP_NEMESI,
DEMUXER_TYPE_MNG,
diff --git a/libmpdemux/extension.c b/libmpdemux/extension.c
index 1d2ffb832e..8c4602bab4 100644
--- a/libmpdemux/extension.c
+++ b/libmpdemux/extension.c
@@ -38,9 +38,6 @@ static struct {
const char *extension;
int demuxer_type;
} extensions_table[] = {
-// { "mpeg", DEMUXER_TYPE_MPEG_PS },
-// { "mpg", DEMUXER_TYPE_MPEG_PS },
-// { "mpe", DEMUXER_TYPE_MPEG_PS },
{ "vob", DEMUXER_TYPE_MPEG_PS },
{ "m2v", DEMUXER_TYPE_MPEG_PS },
{ "avi", DEMUXER_TYPE_AVI },
@@ -58,16 +55,16 @@ static struct {
{ "wav", DEMUXER_TYPE_AUDIO },
{ "flac", DEMUXER_TYPE_AUDIO },
{ "fla", DEMUXER_TYPE_AUDIO },
- { "ogg", DEMUXER_TYPE_OGG },
- { "ogm", DEMUXER_TYPE_OGG },
+ { "ogg", DEMUXER_TYPE_LAVF },
+ { "ogm", DEMUXER_TYPE_LAVF },
// { "pls", DEMUXER_TYPE_PLAYLIST },
// { "m3u", DEMUXER_TYPE_PLAYLIST },
- { "xm", DEMUXER_TYPE_XMMS },
- { "mod", DEMUXER_TYPE_XMMS },
- { "s3m", DEMUXER_TYPE_XMMS },
- { "it", DEMUXER_TYPE_XMMS },
- { "mid", DEMUXER_TYPE_XMMS },
- { "midi", DEMUXER_TYPE_XMMS },
+ { "xm", DEMUXER_TYPE_LAVF },
+ { "mod", DEMUXER_TYPE_LAVF },
+ { "s3m", DEMUXER_TYPE_LAVF },
+ { "it", DEMUXER_TYPE_LAVF },
+ { "mid", DEMUXER_TYPE_LAVF },
+ { "midi", DEMUXER_TYPE_LAVF },
{ "nsv", DEMUXER_TYPE_NSV },
{ "nsa", DEMUXER_TYPE_NSV },
{ "mpc", DEMUXER_TYPE_MPC },
@@ -75,8 +72,8 @@ static struct {
{ "avs", DEMUXER_TYPE_AVS },
#endif
{ "302", DEMUXER_TYPE_LAVF },
- { "264", DEMUXER_TYPE_H264_ES },
- { "26l", DEMUXER_TYPE_H264_ES },
+ { "264", DEMUXER_TYPE_LAVF },
+ { "26l", DEMUXER_TYPE_LAVF },
{ "ac3", DEMUXER_TYPE_LAVF },
{ "ape", DEMUXER_TYPE_LAVF },
{ "apl", DEMUXER_TYPE_LAVF },
diff --git a/libmpdemux/mpeg_hdr.c b/libmpdemux/mpeg_hdr.c
deleted file mode 100644
index 0c368aa7a2..0000000000
--- a/libmpdemux/mpeg_hdr.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * based on libmpeg2/header.c by Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "mpeg_hdr.h"
-#include "libavutil/attributes.h"
-#include "mp_msg.h"
-
-static float frameratecode2framerate[16] = {
- 0,
- // Official mpeg1/2 framerates: (1-8)
- 24000.0/1001, 24,25,
- 30000.0/1001, 30,50,
- 60000.0/1001, 60,
- // Xing's 15fps: (9)
- 15,
- // libmpeg3's "Unofficial economy rates": (10-13)
- 5,10,12,15,
- // some invalid ones: (14-15)
- 0,0
-};
-
-
-int mp_header_process_sequence_header (mp_mpeg_header_t * picture, const unsigned char * buffer)
-{
- int height;
-
- if ((buffer[6] & 0x20) != 0x20){
- fprintf(stderr, "missing marker bit!\n");
- return 1; /* missing marker_bit */
- }
-
- height = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
-
- picture->display_picture_width = height >> 12;
- picture->display_picture_height = height & 0xfff;
-
- picture->aspect_ratio_information = buffer[3] >> 4;
- picture->frame_rate_code = buffer[3] & 15;
- picture->fps=frameratecode2framerate[picture->frame_rate_code];
- picture->bitrate = (buffer[4]<<10)|(buffer[5]<<2)|(buffer[6]>>6);
- picture->mpeg1 = 1;
- picture->picture_structure = 3; //FRAME_PICTURE;
- picture->display_time=100;
- picture->frame_rate_extension_n = 1;
- picture->frame_rate_extension_d = 1;
- return 0;
-}
-
-static int header_process_sequence_extension (mp_mpeg_header_t * picture,
- unsigned char * buffer)
-{
- /* check chroma format, size extensions, marker bit */
-
- if ( ((buffer[1] & 0x06) == 0x00) ||
- ((buffer[1] & 0x01) != 0x00) || (buffer[2] & 0xe0) ||
- ((buffer[3] & 0x01) != 0x01) )
- return 1;
-
- picture->progressive_sequence = (buffer[1] >> 3) & 1;
- picture->frame_rate_extension_n = ((buffer[5] >> 5) & 3) + 1;
- picture->frame_rate_extension_d = (buffer[5] & 0x1f) + 1;
-
- picture->mpeg1 = 0;
- return 0;
-}
-
-static int header_process_picture_coding_extension (mp_mpeg_header_t * picture, unsigned char * buffer)
-{
- picture->picture_structure = buffer[2] & 3;
- picture->top_field_first = buffer[3] >> 7;
- picture->repeat_first_field = (buffer[3] >> 1) & 1;
- picture->progressive_frame = buffer[4] >> 7;
-
- // repeat_first implementation by A'rpi/ESP-team, based on libmpeg3:
- picture->display_time=100;
- if(picture->repeat_first_field){
- if(picture->progressive_sequence){
- if(picture->top_field_first)
- picture->display_time+=200;
- else
- picture->display_time+=100;
- } else
- if(picture->progressive_frame){
- picture->display_time+=50;
- }
- }
- //temopral hack. We calc time on every field, so if we have 2 fields
- // interlaced we'll end with double time for 1 frame
- if( picture->picture_structure!=3 ) picture->display_time/=2;
- return 0;
-}
-
-int mp_header_process_extension (mp_mpeg_header_t * picture, unsigned char * buffer)
-{
- switch (buffer[0] & 0xf0) {
- case 0x10: /* sequence extension */
- return header_process_sequence_extension (picture, buffer);
- case 0x80: /* picture coding extension */
- return header_process_picture_coding_extension (picture, buffer);
- }
- return 0;
-}
-
-float mpeg12_aspect_info(mp_mpeg_header_t *picture)
-{
- float aspect = 0.0;
-
- switch(picture->aspect_ratio_information) {
- case 2: // PAL/NTSC SVCD/DVD 4:3
- case 8: // PAL VCD 4:3
- case 12: // NTSC VCD 4:3
- aspect=4.0/3.0;
- break;
- case 3: // PAL/NTSC Widescreen SVCD/DVD 16:9
- case 6: // (PAL?)/NTSC Widescreen SVCD 16:9
- aspect=16.0/9.0;
- break;
- case 4: // according to ISO-138182-2 Table 6.3
- aspect=2.21;
- break;
- case 1: // VGA 1:1 - do not prescale
- case 9: // Movie Type ??? / 640x480
- aspect=0.0;
- break;
- default:
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Detected unknown aspect_ratio_information in mpeg sequence header.\n"
- "Please report the aspect value (%i) along with the movie type (VGA,PAL,NTSC,"
- "SECAM) and the movie resolution (720x576,352x240,480x480,...) to the MPlayer"
- " developers, so that we can add support for it!\nAssuming 1:1 aspect for now.\n",
- picture->aspect_ratio_information);
- }
-
- return aspect;
-}
-
-//MPEG4 HEADERS
-unsigned char mp_getbits(unsigned char *buffer, unsigned int from, unsigned char len)
-{
- unsigned int n;
- unsigned char m, u, l, y;
-
- n = from / 8;
- m = from % 8;
- u = 8 - m;
- l = (len > u ? len - u : 0);
-
- y = (buffer[n] << m);
- if(8 > len)
- y >>= (8-len);
- if(l)
- y |= (buffer[n+1] >> (8-l));
-
- //fprintf(stderr, "GETBITS(%d -> %d): bytes=0x%x 0x%x, n=%d, m=%d, l=%d, u=%d, Y=%d\n",
- // from, (int) len, (int) buffer[n],(int) buffer[n+1], n, (int) m, (int) l, (int) u, (int) y);
- return y;
-}
-
-static inline unsigned int mp_getbits16(unsigned char *buffer, unsigned int from, unsigned char len)
-{
- if(len > 8)
- return (mp_getbits(buffer, from, len - 8) << 8) | mp_getbits(buffer, from + len - 8, 8);
- else
- return mp_getbits(buffer, from, len);
-}
-
-#define getbits mp_getbits
-#define getbits16 mp_getbits16
-
-static int read_timeinc(mp_mpeg_header_t * picture, unsigned char * buffer, int n)
-{
- if(picture->timeinc_bits > 8) {
- picture->timeinc_unit = getbits(buffer, n, picture->timeinc_bits - 8) << 8;
- n += picture->timeinc_bits - 8;
- picture->timeinc_unit |= getbits(buffer, n, 8);
- n += 8;
- } else {
- picture->timeinc_unit = getbits(buffer, n, picture->timeinc_bits);
- n += picture->timeinc_bits;
- }
- //fprintf(stderr, "TIMEINC2: %d, bits: %d\n", picture->timeinc_unit, picture->timeinc_bits);
- return n;
-}
-
-int mp4_header_process_vol(mp_mpeg_header_t * picture, unsigned char * buffer)
-{
- unsigned int n, aspect=0, aspectw av_unused=0, aspecth av_unused=0, x=1, v;
-
- //begins with 0x0000012x
- picture->fps = 0;
- picture->timeinc_bits = picture->timeinc_resolution = picture->timeinc_unit = 0;
- n = 9;
- if(getbits(buffer, n, 1))
- n += 7;
- n++;
- aspect=getbits(buffer, n, 4);
- n += 4;
- if(aspect == 0x0f) {
- aspectw = getbits(buffer, n, 8);
- n += 8;
- aspecth = getbits(buffer, n, 8);
- n += 8;
- }
-
- if(getbits(buffer, n, 1)) {
- n += 4;
- if(getbits(buffer, n, 1))
- n += 79;
- n++;
- } else n++;
-
- n+=3;
-
- picture->timeinc_resolution = getbits(buffer, n, 8) << 8;
- n += 8;
- picture->timeinc_resolution |= getbits(buffer, n, 8);
- n += 8;
-
- picture->timeinc_bits = 0;
- v = picture->timeinc_resolution - 1;
- while(v && (x<16)) {
- v>>=1;
- picture->timeinc_bits++;
- }
- picture->timeinc_bits = (picture->timeinc_bits > 1 ? picture->timeinc_bits : 1);
-
- n++; //marker bit
-
- if(getbits(buffer, n++, 1)) { //fixed_vop_timeinc
- n += read_timeinc(picture, buffer, n);
-
- if(picture->timeinc_unit)
- picture->fps = (float) picture->timeinc_resolution / (float) picture->timeinc_unit;
- }
-
- n++; //marker bit
- picture->display_picture_width = getbits16(buffer, n, 13);
- n += 13;
- n++; //marker bit
- picture->display_picture_height = getbits16(buffer, n, 13);
- n += 13;
-
- //fprintf(stderr, "ASPECT: %d, PARW=%d, PARH=%d, TIMEINCRESOLUTION: %d, FIXED_TIMEINC: %d (number of bits: %d), FPS: %u\n",
- // aspect, aspectw, aspecth, picture->timeinc_resolution, picture->timeinc_unit, picture->timeinc_bits, picture->fps);
-
- return 0;
-}
-
-void mp4_header_process_vop(mp_mpeg_header_t * picture, unsigned char * buffer)
-{
- int n;
- n = 0;
- picture->picture_type = getbits(buffer, n, 2);
- n += 2;
- while(getbits(buffer, n, 1))
- n++;
- n++;
- getbits(buffer, n, 1);
- n++;
- n += read_timeinc(picture, buffer, n);
-}
-
-#define min(a, b) ((a) <= (b) ? (a) : (b))
-
-static unsigned int read_golomb(unsigned char *buffer, unsigned int *init)
-{
- unsigned int x, v = 0, v2 = 0, m, len = 0, n = *init;
-
- while(getbits(buffer, n++, 1) == 0)
- len++;
-
- x = len + n;
- while(n < x)
- {
- m = min(x - n, 8);
- v |= getbits(buffer, n, m);
- n += m;
- if(x - n > 8)
- v <<= 8;
- }
-
- v2 = 1;
- for(n = 0; n < len; n++)
- v2 <<= 1;
- v2 = (v2 - 1) + v;
-
- //fprintf(stderr, "READ_GOLOMB(%u), V=2^%u + %u-1 = %u\n", *init, len, v, v2);
- *init = x;
- return v2;
-}
-
-inline static int read_golomb_s(unsigned char *buffer, unsigned int *init)
-{
- unsigned int v = read_golomb(buffer, init);
- return (v & 1) ? ((v + 1) >> 1) : -(v >> 1);
-}
-
-static int h264_parse_vui(mp_mpeg_header_t * picture, unsigned char * buf, unsigned int n)
-{
- unsigned int overscan, vsp_color, chroma, timing, fixed_fps;
-
- if(getbits(buf, n++, 1))
- {
- picture->aspect_ratio_information = getbits(buf, n, 8);
- n += 8;
- if(picture->aspect_ratio_information == 255)
- {
- picture->display_picture_width = (getbits(buf, n, 8) << 8) | getbits(buf, n + 8, 8);
- n += 16;
-
- picture->display_picture_height = (getbits(buf, n, 8) << 8) | getbits(buf, n + 8, 8);
- n += 16;
- }
- }
-
- if((overscan=getbits(buf, n++, 1)))
- n++;
- if((vsp_color=getbits(buf, n++, 1)))
- {
- n += 4;
- if(getbits(buf, n++, 1))
- n += 24;
- }
- if((chroma=getbits(buf, n++, 1)))
- {
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- }
- if((timing=getbits(buf, n++, 1)))
- {
- picture->timeinc_unit = (getbits(buf, n, 8) << 24) | (getbits(buf, n+8, 8) << 16) | (getbits(buf, n+16, 8) << 8) | getbits(buf, n+24, 8);
- n += 32;
-
- picture->timeinc_resolution = (getbits(buf, n, 8) << 24) | (getbits(buf, n+8, 8) << 16) | (getbits(buf, n+16, 8) << 8) | getbits(buf, n+24, 8);
- n += 32;
-
- fixed_fps = getbits(buf, n, 1);
-
- if(picture->timeinc_unit > 0 && picture->timeinc_resolution > 0)
- picture->fps = (float) picture->timeinc_resolution / (float) picture->timeinc_unit;
- if(fixed_fps)
- picture->fps /= 2;
- }
-
- //fprintf(stderr, "H264_PARSE_VUI, OVESCAN=%u, VSP_COLOR=%u, CHROMA=%u, TIMING=%u, DISPW=%u, DISPH=%u, TIMERES=%u, TIMEINC=%u, FIXED_FPS=%u\n", overscan, vsp_color, chroma, timing, picture->display_picture_width, picture->display_picture_height,
- // picture->timeinc_resolution, picture->timeinc_unit, picture->timeinc_unit, fixed_fps);
-
- return n;
-}
-
-static int mp_unescape03(unsigned char *buf, int len)
-{
- unsigned char *dest;
- int i, j, skip;
-
- dest = malloc(len);
- if(! dest)
- return 0;
-
- j = i = skip = 0;
- while(i <= len-3)
- {
- if(buf[i] == 0 && buf[i+1] == 0 && buf[i+2] == 3)
- {
- dest[j] = dest[j+1] = 0;
- j += 2;
- i += 3;
- skip++;
- }
- else
- {
- dest[j] = buf[i];
- j++;
- i++;
- }
- }
- dest[j] = buf[len-2];
- dest[j+1] = buf[len-1];
- len -= skip;
- memcpy(buf, dest, len);
- free(dest);
-
- return len;
-}
-
-int h264_parse_sps(mp_mpeg_header_t * picture, unsigned char * buf, int len)
-{
- unsigned int n = 0, v, i, k, mbh;
- int frame_mbs_only;
-
- len = mp_unescape03(buf, len);
-
- picture->fps = picture->timeinc_unit = picture->timeinc_resolution = 0;
- n = 24;
- read_golomb(buf, &n);
- if(buf[0] >= 100){
- if(read_golomb(buf, &n) == 3)
- n++;
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- n++;
- if(getbits(buf, n++, 1)){
- for(i = 0; i < 8; i++)
- { // scaling list is skipped for now
- if(getbits(buf, n++, 1))
- {
- v = 8;
- for(k = (i < 6 ? 16 : 64); k && v; k--)
- v = (v + read_golomb_s(buf, &n)) & 255;
- }
- }
- }
- }
- read_golomb(buf, &n);
- v = read_golomb(buf, &n);
- if(v == 0)
- read_golomb(buf, &n);
- else if(v == 1)
- {
- getbits(buf, n++, 1);
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- v = read_golomb(buf, &n);
- for(i = 0; i < v; i++)
- read_golomb(buf, &n);
- }
- read_golomb(buf, &n);
- getbits(buf, n++, 1);
- picture->display_picture_width = 16 *(read_golomb(buf, &n)+1);
- mbh = read_golomb(buf, &n)+1;
- frame_mbs_only = getbits(buf, n++, 1);
- picture->display_picture_height = 16 * (2 - frame_mbs_only) * mbh;
- if(!frame_mbs_only)
- getbits(buf, n++, 1);
- getbits(buf, n++, 1);
- if(getbits(buf, n++, 1))
- {
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- read_golomb(buf, &n);
- }
- if(getbits(buf, n++, 1))
- n = h264_parse_vui(picture, buf, n);
-
- return n;
-}
-
-int mp_vc1_decode_sequence_header(mp_mpeg_header_t * picture, unsigned char * buf, int len)
-{
- int n, x;
-
- len = mp_unescape03(buf, len);
-
- picture->display_picture_width = picture->display_picture_height = 0;
- picture->fps = 0;
- n = 0;
- x = getbits(buf, n, 2);
- n += 2;
- if(x != 3) //not advanced profile
- return 0;
-
- getbits16(buf, n, 14);
- n += 14;
- picture->display_picture_width = getbits16(buf, n, 12) * 2 + 2;
- n += 12;
- picture->display_picture_height = getbits16(buf, n, 12) * 2 + 2;
- n += 12;
- getbits(buf, n, 6);
- n += 6;
- x = getbits(buf, n, 1);
- n += 1;
- if(x) //display info
- {
- getbits16(buf, n, 14);
- n += 14;
- getbits16(buf, n, 14);
- n += 14;
- if(getbits(buf, n++, 1)) //aspect ratio
- {
- x = getbits(buf, n, 4);
- n += 4;
- if(x == 15)
- {
- getbits16(buf, n, 16);
- n += 16;
- }
- }
-
- if(getbits(buf, n++, 1)) //framerates
- {
- int frexp=0, frnum=0, frden=0;
-
- if(getbits(buf, n++, 1))
- {
- frexp = getbits16(buf, n, 16);
- n += 16;
- picture->fps = (double) (frexp+1) / 32.0;
- }
- else
- {
- float frates[] = {0, 24000, 25000, 30000, 50000, 60000, 48000, 72000, 0};
- float frdivs[] = {0, 1000, 1001, 0};
-
- frnum = getbits(buf, n, 8);
- n += 8;
- frden = getbits(buf, n, 4);
- n += 4;
- if((frden == 1 || frden == 2) && (frnum < 8))
- picture->fps = frates[frnum] / frdivs[frden];
- }
- }
- }
-
- //free(dest);
- return 1;
-}
diff --git a/libmpdemux/mpeg_hdr.h b/libmpdemux/mpeg_hdr.h
deleted file mode 100644
index ccd84bcdb0..0000000000
--- a/libmpdemux/mpeg_hdr.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_MPEG_HDR_H
-#define MPLAYER_MPEG_HDR_H
-
-typedef struct {
- // video info:
- int mpeg1; // 0=mpeg2 1=mpeg1
- int display_picture_width;
- int display_picture_height;
- int aspect_ratio_information;
- int frame_rate_code;
- float fps;
- int frame_rate_extension_n;
- int frame_rate_extension_d;
- int bitrate; // 0x3FFFF==VBR
- // timing:
- int picture_structure;
- int progressive_sequence;
- int repeat_first_field;
- int progressive_frame;
- int top_field_first;
- int display_time; // secs*100
- //the following are for mpeg4
- unsigned int timeinc_resolution, timeinc_bits, timeinc_unit;
- int picture_type;
-} mp_mpeg_header_t;
-
-int mp_header_process_sequence_header (mp_mpeg_header_t * picture, const unsigned char * buffer);
-int mp_header_process_extension (mp_mpeg_header_t * picture, unsigned char * buffer);
-float mpeg12_aspect_info(mp_mpeg_header_t *picture);
-int mp4_header_process_vol(mp_mpeg_header_t * picture, unsigned char * buffer);
-void mp4_header_process_vop(mp_mpeg_header_t * picture, unsigned char * buffer);
-int h264_parse_sps(mp_mpeg_header_t * picture, unsigned char * buf, int len);
-int mp_vc1_decode_sequence_header(mp_mpeg_header_t * picture, unsigned char * buf, int len);
-
-unsigned char mp_getbits(unsigned char *buffer, unsigned int from, unsigned char len);
-
-#endif /* MPLAYER_MPEG_HDR_H */
diff --git a/libmpdemux/parse_es.c b/libmpdemux/parse_es.c
deleted file mode 100644
index 05507a495a..0000000000
--- a/libmpdemux/parse_es.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * MPEG-ES video parser
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "parse_es.h"
-
-//static unsigned char videobuffer[MAX_VIDEO_PACKET_SIZE];
-unsigned char* videobuffer=NULL;
-int videobuf_len=0;
-int next_nal = -1;
-///! legacy variable, 4 if stream is synced, 0 if not
-int videobuf_code_len=0;
-
-#define MAX_SYNCLEN (10 * 1024 * 1024)
-// sync video stream, and returns next packet code
-int sync_video_packet(demux_stream_t *ds){
- if (!videobuf_code_len) {
- int skipped=0;
- if (!demux_pattern_3(ds, NULL, MAX_SYNCLEN, &skipped, 0x100)) {
- if (skipped == MAX_SYNCLEN)
- mp_msg(MSGT_DEMUXER, MSGL_ERR, "parse_es: could not sync video stream!\n");
- goto eof_out;
- }
- next_nal = demux_getc(ds);
- if (next_nal < 0)
- goto eof_out;
- videobuf_code_len = 4;
- if(skipped) mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: %d bytes skipped (next: 0x1%02X)\n",skipped,next_nal);
- }
- return 0x100|next_nal;
-
-eof_out:
- next_nal = -1;
- videobuf_code_len = 0;
- return 0;
-}
-
-// return: packet length
-int read_video_packet(demux_stream_t *ds){
-int packet_start;
- int res, read;
-
- if (VIDEOBUFFER_SIZE - videobuf_len < 5)
- return 0;
- // SYNC STREAM
-// if(!sync_video_packet(ds)) return 0; // cannot sync (EOF)
-
- // COPY STARTCODE:
- packet_start=videobuf_len;
- videobuffer[videobuf_len+0]=0;
- videobuffer[videobuf_len+1]=0;
- videobuffer[videobuf_len+2]=1;
- videobuffer[videobuf_len+3]=next_nal;
- videobuf_len+=4;
-
- // READ PACKET:
- res = demux_pattern_3(ds, &videobuffer[videobuf_len],
- VIDEOBUFFER_SIZE - videobuf_len, &read, 0x100);
- videobuf_len += read;
- if (!res)
- goto eof_out;
-
- videobuf_len-=3;
-
- mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: packet 0x1%02X len=%d (total=%d)\n",videobuffer[packet_start+3],videobuf_len-packet_start,videobuf_len);
-
- // Save next packet code:
- next_nal = demux_getc(ds);
- if (next_nal < 0)
- goto eof_out;
- videobuf_code_len=4;
-
- return videobuf_len-packet_start;
-
-eof_out:
- next_nal = -1;
- videobuf_code_len = 0;
- return videobuf_len - packet_start;
-}
-
-// return: next packet code
-int skip_video_packet(demux_stream_t *ds){
-
- // SYNC STREAM
-// if(!sync_video_packet(ds)) return 0; // cannot sync (EOF)
-
- videobuf_code_len=0; // force resync
-
- // SYNC AGAIN:
- return sync_video_packet(ds);
-}
-
-/* stripped down version of a52_syncinfo() from liba52
- * copyright belongs to Michel Lespinasse <walken@zoy.org>
- * and Aaron Holtzman <aholtzma@ess.engr.uvic.ca> */
-int mp_a52_framesize(uint8_t * buf, int *srate)
-{
- int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
- 128, 160, 192, 224, 256, 320, 384, 448,
- 512, 576, 640
- };
- uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
- int frmsizecod, bitrate, half;
-
- if ((buf[0] != 0x0b) || (buf[1] != 0x77)) /* syncword */
- return 0;
-
- if (buf[5] >= 0x60) /* bsid >= 12 */
- return 0;
-
- half = halfrate[buf[5] >> 3];
-
- frmsizecod = buf[4] & 63;
- if (frmsizecod >= 38)
- return 0;
-
- bitrate = rate[frmsizecod >> 1];
-
- switch (buf[4] & 0xc0) {
- case 0: /* 48 KHz */
- *srate = 48000 >> half;
- return 4 * bitrate;
- case 0x40: /* 44.1 KHz */
- *srate = 44100 >> half;
- return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
- case 0x80: /* 32 KHz */
- *srate = 32000 >> half;
- return 6 * bitrate;
- }
-
- return 0;
-}
diff --git a/libmpdemux/parse_es.h b/libmpdemux/parse_es.h
deleted file mode 100644
index ed76593e50..0000000000
--- a/libmpdemux/parse_es.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_PARSE_ES_H
-#define MPLAYER_PARSE_ES_H
-
-#include <stdint.h>
-
-#include "demuxer.h"
-
-#define MAX_VIDEO_PACKET_SIZE (224*1024+4)
-#define VIDEOBUFFER_SIZE 0x100000
-
-extern unsigned char* videobuffer;
-extern int videobuf_len;
-extern unsigned char videobuf_code[4];
-extern int videobuf_code_len;
-
-// sync video stream, and returns next packet code
-int sync_video_packet(demux_stream_t *ds);
-
-// return: packet length
-int read_video_packet(demux_stream_t *ds);
-
-// return: next packet code
-int skip_video_packet(demux_stream_t *ds);
-
-int mp_a52_framesize(uint8_t *buf, int *srate);
-
-#endif /* MPLAYER_PARSE_ES_H */
diff --git a/libmpdemux/parse_mp4.c b/libmpdemux/parse_mp4.c
deleted file mode 100644
index 137ec3e6e7..0000000000
--- a/libmpdemux/parse_mp4.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * MP4 file format parser code
- *
- * Copyright (C) 2002 Felix Buenemann <atmosfear at users.sourceforge.net>
- * Code inspired by libmp4 from http://mpeg4ip.sourceforge.net/.
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include "parse_mp4.h"
-#include "mp_msg.h"
-#include "stream/stream.h"
-
-//#define MP4_DUMPATOM
-
-#define MP4_DL MSGL_V
-#define freereturn(a,b) free(a); return b
-
-static int mp4_read_descr_len(stream_t *s)
-{
- uint8_t b;
- uint8_t numBytes = 0;
- uint32_t length = 0;
-
- do {
- b = stream_read_char(s);
- numBytes++;
- length = (length << 7) | (b & 0x7F);
- } while ((b & 0x80) && numBytes < 4);
-
- //printf("MP4 read desc len: %d\n", length);
- return length;
-}
-
-/* parse the data part of MP4 esds atoms */
-int mp4_parse_esds(unsigned char *data, int datalen, esds_t *esds) {
- /* create memory stream from data */
- stream_t *s = new_memory_stream(data, datalen);
- uint16_t len;
-#ifdef MP4_DUMPATOM
- {int i;
- printf("ESDS Dump (%dbyte):\n", datalen);
- for(i = 0; i < datalen; i++)
- printf("%02X ", data[i]);
- printf("\nESDS Dumped\n");}
-#endif
- memset(esds, 0, sizeof(esds_t));
-
- esds->version = stream_read_char(s);
- esds->flags = stream_read_int24(s);
- mp_msg(MSGT_DEMUX, MP4_DL,
- "ESDS MPEG4 version: %d flags: 0x%06X\n",
- esds->version, esds->flags);
-
- /* get and verify ES_DescrTag */
- if (stream_read_char(s) == MP4ESDescrTag) {
- /* read length */
- len = mp4_read_descr_len(s);
-
- esds->ESId = stream_read_word(s);
- esds->streamPriority = stream_read_char(s);
- mp_msg(MSGT_DEMUX, MP4_DL,
- "ESDS MPEG4 ES Descriptor (%dBytes):\n"
- " -> ESId: %d\n"
- " -> streamPriority: %d\n",
- len, esds->ESId, esds->streamPriority);
-
- if (len < (5 + 15)) {
- freereturn(s,1);
- }
- } else {
- esds->ESId = stream_read_word(s);
- mp_msg(MSGT_DEMUX, MP4_DL,
- "ESDS MPEG4 ES Descriptor (%dBytes):\n"
- " -> ESId: %d\n", 2, esds->ESId);
- }
-
- /* get and verify DecoderConfigDescrTab */
- if (stream_read_char(s) != MP4DecConfigDescrTag) {
- freereturn(s,1);
- }
-
- /* read length */
- len = mp4_read_descr_len(s);
-
- esds->objectTypeId = stream_read_char(s);
- esds->streamType = stream_read_char(s);
- esds->bufferSizeDB = stream_read_int24(s);
- esds->maxBitrate = stream_read_dword(s);
- esds->avgBitrate = stream_read_dword(s);
- mp_msg(MSGT_DEMUX, MP4_DL,
- "ESDS MPEG4 Decoder Config Descriptor (%dBytes):\n"
- " -> objectTypeId: %d\n"
- " -> streamType: 0x%02X\n"
- " -> bufferSizeDB: 0x%06X\n"
- " -> maxBitrate: %.3fkbit/s\n"
- " -> avgBitrate: %.3fkbit/s\n",
- len, esds->objectTypeId, esds->streamType,
- esds->bufferSizeDB, esds->maxBitrate/1000.0,
- esds->avgBitrate/1000.0);
-
- esds->decoderConfigLen=0;
-
- if (len < 15) {
- freereturn(s,0);
- }
-
- /* get and verify DecSpecificInfoTag */
- if (stream_read_char(s) != MP4DecSpecificDescrTag) {
- freereturn(s,0);
- }
-
- /* read length */
- esds->decoderConfigLen = len = mp4_read_descr_len(s);
-
- esds->decoderConfig = malloc(esds->decoderConfigLen);
- if (esds->decoderConfig) {
- stream_read(s, esds->decoderConfig, esds->decoderConfigLen);
- } else {
- esds->decoderConfigLen = 0;
- }
- mp_msg(MSGT_DEMUX, MP4_DL,
- "ESDS MPEG4 Decoder Specific Descriptor (%dBytes)\n", len);
-
- /* get and verify SLConfigDescrTag */
- if(stream_read_char(s) != MP4SLConfigDescrTag) {
- freereturn(s,0);
- }
-
- /* Note: SLConfig is usually constant value 2, size 1Byte */
- esds->SLConfigLen = len = mp4_read_descr_len(s);
- esds->SLConfig = malloc(esds->SLConfigLen);
- if (esds->SLConfig) {
- stream_read(s, esds->SLConfig, esds->SLConfigLen);
- } else {
- esds->SLConfigLen = 0;
- }
- mp_msg(MSGT_DEMUX, MP4_DL,
- "ESDS MPEG4 Sync Layer Config Descriptor (%dBytes)\n"
- " -> predefined: %d\n", len, esds->SLConfig[0]);
-
- /* will skip the remainder of the atom */
- freereturn(s,0);
-
-}
-
-/* cleanup all mem occupied by mp4_parse_esds */
-void mp4_free_esds(esds_t *esds) {
- if(esds->decoderConfigLen)
- free(esds->decoderConfig);
- if(esds->SLConfigLen)
- free(esds->SLConfig);
-}
-
-#undef freereturn
-#undef MP4_DL
diff --git a/libmpdemux/parse_mp4.h b/libmpdemux/parse_mp4.h
deleted file mode 100644
index 27d4d44d7d..0000000000
--- a/libmpdemux/parse_mp4.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * MP4 file format parser code
- *
- * Copyright (C) 2002 Felix Buenemann <atmosfear at users.sourceforge.net>
- * Code inspired by libmp4 from http://mpeg4ip.sourceforge.net/.
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_PARSE_MP4_H
-#define MPLAYER_PARSE_MP4_H
-
-#include <inttypes.h>
-
-/* one byte tag identifiers */
-#define MP4ODescrTag 0x01
-#define MP4IODescrTag 0x02
-#define MP4ESDescrTag 0x03
-#define MP4DecConfigDescrTag 0x04
-#define MP4DecSpecificDescrTag 0x05
-#define MP4SLConfigDescrTag 0x06
-#define MP4ContentIdDescrTag 0x07
-#define MP4SupplContentIdDescrTag 0x08
-#define MP4IPIPtrDescrTag 0x09
-#define MP4IPMPPtrDescrTag 0x0A
-#define MP4IPMPDescrTag 0x0B
-#define MP4RegistrationDescrTag 0x0D
-#define MP4ESIDIncDescrTag 0x0E
-#define MP4ESIDRefDescrTag 0x0F
-#define MP4FileIODescrTag 0x10
-#define MP4FileODescrTag 0x11
-#define MP4ExtProfileLevelDescrTag 0x13
-#define MP4ExtDescrTagsStart 0x80
-#define MP4ExtDescrTagsEnd 0xFE
-
-/* object type identifiers in the ESDS */
-/* See http://gpac.sourceforge.net/tutorial/mediatypes.htm */
-/* BIFS stream version 1 */
-#define MP4OTI_MPEG4Systems1 0x01
-/* BIFS stream version 2 */
-#define MP4OTI_MPEG4Systems2 0x02
-/* MPEG-4 visual stream */
-#define MP4OTI_MPEG4Visual 0x20
-/* MPEG-4 audio stream */
-#define MP4OTI_MPEG4Audio 0x40
-/* MPEG-2 visual streams with various profiles */
-#define MP4OTI_MPEG2VisualSimple 0x60
-#define MP4OTI_MPEG2VisualMain 0x61
-#define MP4OTI_MPEG2VisualSNR 0x62
-#define MP4OTI_MPEG2VisualSpatial 0x63
-#define MP4OTI_MPEG2VisualHigh 0x64
-#define MP4OTI_MPEG2Visual422 0x65
-/* MPEG-2 audio stream part 7 ("AAC") with various profiles */
-#define MP4OTI_MPEG2AudioMain 0x66
-#define MP4OTI_MPEG2AudioLowComplexity 0x67
-#define MP4OTI_MPEG2AudioScaleableSamplingRate 0x68
-/* MPEG-2 audio part 3 ("MP3") */
-#define MP4OTI_MPEG2AudioPart3 0x69
-/* MPEG-1 visual visual stream */
-#define MP4OTI_MPEG1Visual 0x6A
-/* MPEG-1 audio stream part 3 ("MP3") */
-#define MP4OTI_MPEG1Audio 0x6B
-/* JPEG visual stream */
-#define MP4OTI_JPEG 0x6C
-/* 3GPP2 */
-#define MP4OTI_13kVoice 0xE1
-
-/* I define uint24 here for better understanding */
-#ifndef uint24_t
-#define uint24_t uint32_t
-#endif
-
-/* esds_t */
-typedef struct {
- uint8_t version;
- uint24_t flags;
-
- /* 0x03 ESDescrTag */
- uint16_t ESId;
- uint8_t streamPriority;
-
- /* 0x04 DecConfigDescrTag */
- uint8_t objectTypeId;
- uint8_t streamType;
- /* XXX: really streamType is
- * only 6bit, followed by:
- * 1bit upStream
- * 1bit reserved
- */
- uint24_t bufferSizeDB;
- uint32_t maxBitrate;
- uint32_t avgBitrate;
-
- /* 0x05 DecSpecificDescrTag */
- uint16_t decoderConfigLen;
- uint8_t *decoderConfig;
-
- /* 0x06 SLConfigDescrTag */
- uint8_t SLConfigLen;
- uint8_t *SLConfig;
-
- /* TODO: add the missing tags,
- * I currently have no specs
- * for them and doubt they
- * are currently needed ::atmos
- */
-
-} esds_t;
-
-int mp4_parse_esds(unsigned char *data, int datalen, esds_t *esds);
-void mp4_free_esds(esds_t *esds);
-
-#endif /* MPLAYER_PARSE_MP4_H */
diff --git a/libmpdemux/video.c b/libmpdemux/video.c
index e788818825..7bb1ade6e0 100644
--- a/libmpdemux/video.c
+++ b/libmpdemux/video.c
@@ -36,8 +36,6 @@
#include "demux_ty_osd.h"
#endif
#include "stheader.h"
-#include "parse_es.h"
-#include "mpeg_hdr.h"
/* sub_cc (closed captions)*/
#include "sub/sub_cc.h"
@@ -49,64 +47,9 @@
#include "demux_rtp.h"
#endif
-static mp_mpeg_header_t picture;
-
-static int telecine=0;
-static float telecine_cnt=-2.5;
-
-typedef enum {
- VIDEO_MPEG12,
- VIDEO_MPEG4,
- VIDEO_H264,
- VIDEO_VC1,
- VIDEO_OTHER
-} video_codec_t;
-
-static video_codec_t find_video_codec(sh_video_t *sh_video)
-{
- demux_stream_t *d_video=sh_video->ds;
- int fmt = d_video->demuxer->file_format;
-
- if(
- (fmt == DEMUXER_TYPE_PVA) ||
- (fmt == DEMUXER_TYPE_MPEG_ES) ||
- (fmt == DEMUXER_TYPE_MPEG_GXF) ||
- (fmt == DEMUXER_TYPE_MPEG_PES) ||
- (
- (fmt == DEMUXER_TYPE_MPEG_PS || fmt == DEMUXER_TYPE_MPEG_TS) &&
- ((! sh_video->format) || (sh_video->format==0x10000001) || (sh_video->format==0x10000002))
- ) ||
- (fmt == DEMUXER_TYPE_MPEG_TY)
-#ifdef CONFIG_LIVE555
- || ((fmt == DEMUXER_TYPE_RTP) && demux_is_mpeg_rtp_stream(d_video->demuxer))
-#endif
- )
- return VIDEO_MPEG12;
- else if((fmt == DEMUXER_TYPE_MPEG4_ES) ||
- ((fmt == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000004)) ||
- ((fmt == DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000004))
- )
- return VIDEO_MPEG4;
- else if((fmt == DEMUXER_TYPE_H264_ES) ||
- ((fmt == DEMUXER_TYPE_MPEG_TS) && (sh_video->format==0x10000005)) ||
- ((fmt == DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000005))
- )
- return VIDEO_H264;
- else if((fmt == DEMUXER_TYPE_MPEG_PS || fmt == DEMUXER_TYPE_MPEG_TS) &&
- (sh_video->format==mmioFOURCC('W', 'V', 'C', '1')))
- return VIDEO_VC1;
- else if (fmt == DEMUXER_TYPE_ASF && sh_video->bih && sh_video->bih->biCompression == mmioFOURCC('D', 'V', 'R', ' '))
- return VIDEO_MPEG12;
- else
- return VIDEO_OTHER;
-}
-
int video_read_properties(sh_video_t *sh_video){
demux_stream_t *d_video=sh_video->ds;
-video_codec_t video_codec = find_video_codec(sh_video);
-// Determine image properties:
-switch(video_codec){
- case VIDEO_OTHER: {
+
if((d_video->demuxer->file_format == DEMUXER_TYPE_ASF) || (d_video->demuxer->file_format == DEMUXER_TYPE_AVI)) {
// display info:
// in case no strf chunk has been seen in avi, we have no bitmap header
@@ -115,464 +58,22 @@ switch(video_codec){
sh_video->disp_w=sh_video->bih->biWidth;
sh_video->disp_h=abs(sh_video->bih->biHeight);
}
- break;
- }
- case VIDEO_MPEG4: {
- int pos = 0, vop_cnt=0, units[3];
- videobuf_len=0; videobuf_code_len=0;
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for Video Object Start code... ");
- while(1){
- int i=sync_video_packet(d_video);
- if(i<=0x11F) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- if(!videobuffer) {
- videobuffer = memalign(8, VIDEOBUFFER_SIZE + MP_INPUT_BUFFER_PADDING_SIZE);
- if (videobuffer) memset(videobuffer+VIDEOBUFFER_SIZE, 0, MP_INPUT_BUFFER_PADDING_SIZE);
- else {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"Cannot allocate shared memory.\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for Video Object Layer Start code... ");
- while(1){
- int i=sync_video_packet(d_video);
- mp_msg(MSGT_DECVIDEO,MSGL_V,"M4V: 0x%X\n",i);
- if(i>=0x120 && i<=0x12F) break; // found it!
- if(!i || !read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- pos = videobuf_len+4;
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read Video Object Layer Header\n");
- return 0;
- }
- mp4_header_process_vol(&picture, &(videobuffer[pos]));
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK! FPS SEEMS TO BE %.3f\nSearching for Video Object Plane Start code... ", sh_video->fps);
- mp4_init:
- while(1){
- int i=sync_video_packet(d_video);
- if(i==0x1B6) break; // found it!
- if(!i || !read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- pos = videobuf_len+4;
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read Video Object Plane Header\n");
- return 0;
- }
- mp4_header_process_vop(&picture, &(videobuffer[pos]));
- sh_video->disp_w = picture.display_picture_width;
- sh_video->disp_h = picture.display_picture_height;
- units[vop_cnt] = picture.timeinc_unit;
- vop_cnt++;
- //mp_msg(MSGT_DECVIDEO,MSGL_V, "TYPE: %d, unit: %d\n", picture.picture_type, picture.timeinc_unit);
- if(!picture.fps) {
- int i, mn, md, mx, diff;
- if(vop_cnt < 3)
- goto mp4_init;
-
- i=0;
- mn = mx = units[0];
- for(i=0; i<3; i++) {
- if(units[i] < mn)
- mn = units[i];
- if(units[i] > mx)
- mx = units[i];
- }
- md = mn;
- for(i=0; i<3; i++) {
- if((units[i] > mn) && (units[i] < mx))
- md = units[i];
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V, "MIN: %d, mid: %d, max: %d\n", mn, md, mx);
- if(mx - md > md - mn)
- diff = md - mn;
- else
- diff = mx - md;
- if(diff > 0){
- picture.fps = ((float)picture.timeinc_resolution) / diff;
- mp_msg(MSGT_DECVIDEO,MSGL_V, "FPS seems to be: %f, resolution: %d, delta_units: %d\n", picture.fps, picture.timeinc_resolution, diff);
- }
- }
- if(picture.fps) {
- sh_video->fps=picture.fps;
- sh_video->frametime=1.0/picture.fps;
- mp_msg(MSGT_DECVIDEO,MSGL_INFO, "FPS seems to be: %f\n", picture.fps);
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- sh_video->format=0x10000004;
- break;
- }
- case VIDEO_H264: {
- int pos = 0;
- videobuf_len=0; videobuf_code_len=0;
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for sequence parameter set... ");
- while(1){
- int i=sync_video_packet(d_video);
- if((i&~0x60) == 0x107 && i != 0x107) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- if(!videobuffer) {
- videobuffer = memalign(8, VIDEOBUFFER_SIZE + MP_INPUT_BUFFER_PADDING_SIZE);
- if (videobuffer) memset(videobuffer+VIDEOBUFFER_SIZE, 0, MP_INPUT_BUFFER_PADDING_SIZE);
- else {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"Cannot allocate shared memory.\n");
- return 0;
- }
- }
- pos = videobuf_len+4;
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Can't read sequence parameter set\n");
- return 0;
- }
- h264_parse_sps(&picture, &(videobuffer[pos]), videobuf_len - pos);
- sh_video->disp_w=picture.display_picture_width;
- sh_video->disp_h=picture.display_picture_height;
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for picture parameter set... ");
- while(1){
- int i=sync_video_packet(d_video);
- mp_msg(MSGT_DECVIDEO,MSGL_V,"H264: 0x%X\n",i);
- if((i&~0x60) == 0x108 && i != 0x108) break; // found it!
- if(!i || !read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\nSearching for Slice... ");
- while(1){
- int i=sync_video_packet(d_video);
- if((i&~0x60) == 0x101 || (i&~0x60) == 0x102 || (i&~0x60) == 0x105) break; // found it!
- if(!i || !read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- sh_video->format=0x10000005;
- if(picture.fps) {
- sh_video->fps=picture.fps;
- sh_video->frametime=1.0/picture.fps;
- mp_msg(MSGT_DECVIDEO,MSGL_INFO, "FPS seems to be: %f\n", picture.fps);
- }
- break;
- }
- case VIDEO_MPEG12: {
- if (d_video->demuxer->file_format == DEMUXER_TYPE_ASF) { // DVR-MS
- if(!sh_video->bih) return 0;
- sh_video->format=sh_video->bih->biCompression;
- }
-mpeg_header_parser:
- // Find sequence_header first:
- videobuf_len=0; videobuf_code_len=0;
- telecine=0; telecine_cnt=-2.5;
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Searching for sequence header... ");
- while(1){
- int i=sync_video_packet(d_video);
- if(i==0x1B3) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- if( mp_msg_test(MSGT_DECVIDEO,MSGL_V) ) mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"MPEG: FATAL: EOF while searching for sequence header.\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_V,"OK!\n");
- // ========= Read & process sequence header & extension ============
- if(!videobuffer) {
- videobuffer = memalign(8, VIDEOBUFFER_SIZE + MP_INPUT_BUFFER_PADDING_SIZE);
- if (videobuffer) memset(videobuffer+VIDEOBUFFER_SIZE, 0, MP_INPUT_BUFFER_PADDING_SIZE);
- else {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"Cannot allocate shared memory.\n");
- return 0;
- }
- }
-
- if(!read_video_packet(d_video)){
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"FATAL: Cannot read sequence header.\n");
- return 0;
- }
- if(mp_header_process_sequence_header (&picture, &videobuffer[4])) {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"MPEG: bad sequence header\n");
- goto mpeg_header_parser;
- }
- if(sync_video_packet(d_video)==0x1B5){ // next packet is seq. ext.
- int pos=videobuf_len;
- if(!read_video_packet(d_video)){
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"FATAL: Cannot read sequence header extension.\n");
- return 0;
- }
- if(mp_header_process_extension (&picture, &videobuffer[pos+4])) {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"MPEG: bad sequence header extension\n");
- return 0;
- }
- }
-
- // display info:
- sh_video->format=picture.mpeg1?0x10000001:0x10000002; // mpeg video
- sh_video->fps=picture.fps * picture.frame_rate_extension_n / picture.frame_rate_extension_d;
- if(!sh_video->fps){
- sh_video->frametime=0;
- } else {
- sh_video->frametime=1.0/sh_video->fps;
- }
- sh_video->disp_w=picture.display_picture_width;
- sh_video->disp_h=picture.display_picture_height;
- // bitrate:
- if(picture.bitrate!=0x3FFFF) // unspecified/VBR ?
- sh_video->i_bps=picture.bitrate * 400 / 8;
- // info:
- mp_dbg(MSGT_DECVIDEO,MSGL_DBG2,"mpeg bitrate: %d (%X)\n",picture.bitrate,picture.bitrate);
- mp_msg(MSGT_DECVIDEO,MSGL_INFO,"VIDEO: %s %dx%d (aspect %d) %5.3f fps %5.1f kbps (%4.1f kbyte/s)\n",
- picture.mpeg1?"MPEG1":"MPEG2",
- sh_video->disp_w,sh_video->disp_h,
- picture.aspect_ratio_information,
- sh_video->fps,
- sh_video->i_bps * 8 / 1000.0,
- sh_video->i_bps / 1000.0 );
- break;
- }
- case VIDEO_VC1: {
- // Find sequence_header:
- videobuf_len=0;
- videobuf_code_len=0;
- mp_msg(MSGT_DECVIDEO,MSGL_INFO,"Searching for VC1 sequence header... ");
- while(1){
- int i=sync_video_packet(d_video);
- if(i==0x10F) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- if( mp_msg_test(MSGT_DECVIDEO,MSGL_V) ) mp_msg(MSGT_DECVIDEO,MSGL_V,"NONE :(\n");
- mp_msg(MSGT_DECVIDEO,MSGL_ERR, "Couldn't find VC-1 sequence header\n");
- return 0;
- }
- }
- mp_msg(MSGT_DECVIDEO,MSGL_INFO,"found\n");
- if(!videobuffer) {
- videobuffer = memalign(8, VIDEOBUFFER_SIZE + MP_INPUT_BUFFER_PADDING_SIZE);
- if (videobuffer) memset(videobuffer+VIDEOBUFFER_SIZE, 0, MP_INPUT_BUFFER_PADDING_SIZE);
- else {
- mp_tmsg(MSGT_DECVIDEO,MSGL_ERR,"Cannot allocate shared memory.\n");
- return 0;
- }
- }
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_ERR, "Couldn't read VC-1 sequence header!\n");
- return 0;
- }
-
- while(1) {
- int i=sync_video_packet(d_video);
- if(i==0x10E) break; // found it!
- if(!i || !skip_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Couldn't find VC-1 entry point sync-code:(\n");
- return 0;
- }
- }
- if(!read_video_packet(d_video)){
- mp_msg(MSGT_DECVIDEO,MSGL_V,"Couldn't read VC-1 entry point sync-code:(\n");
- return 0;
- }
-
- if(mp_vc1_decode_sequence_header(&picture, &videobuffer[4], videobuf_len-4)) {
- sh_video->bih = calloc(1, sizeof(*sh_video->bih) + videobuf_len);
- if(sh_video->bih == NULL) {
- mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Couldn't alloc %zu bytes for VC-1 extradata!\n", sizeof(*sh_video->bih) + videobuf_len);
- return 0;
- }
- sh_video->bih->biSize= sizeof(*sh_video->bih) + videobuf_len;
- memcpy(sh_video->bih + 1, videobuffer, videobuf_len);
- sh_video->bih->biCompression = sh_video->format;
- sh_video->bih->biWidth = sh_video->disp_w = picture.display_picture_width;
- sh_video->bih->biHeight = sh_video->disp_h = picture.display_picture_height;
- if(picture.fps > 0) {
- sh_video->frametime=1.0/picture.fps;
- sh_video->fps = picture.fps;
- }
- mp_msg(MSGT_DECVIDEO,MSGL_INFO,"VIDEO: VC-1 %dx%d, %5.3f fps, header len: %d\n",
- sh_video->disp_w, sh_video->disp_h, sh_video->fps, videobuf_len);
- }
- break;
- }
-} // switch(file_format)
return 1;
}
-static void process_userdata(const unsigned char* buf,int len){
- int i;
- /* if the user data starts with "CC", assume it is a CC info packet */
- if(len>2 && buf[0]=='C' && buf[1]=='C'){
-// mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"video.c: process_userdata() detected Closed Captions!\n");
- subcc_process_data(buf+2,len-2);
- }
-#ifdef DEMUX_TY_OSD
- if( len > 2 && buf[ 0 ] == 'T' && buf[ 1 ] == 'Y' )
- {
- ty_processuserdata( buf + 2, len - 2 );
- return;
- }
-#endif
- if(verbose<2) return;
- fprintf(stderr, "user_data: len=%3d %02X %02X %02X %02X '",
- len, buf[0], buf[1], buf[2], buf[3]);
- for(i=0;i<len;i++)
-// if(buf[i]>=32 && buf[i]<127) fputc(buf[i], stderr);
- if(buf[i]&0x60) fputc(buf[i]&0x7F, stderr);
- fprintf(stderr, "'\n");
-}
-
int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char** start,int force_fps){
demux_stream_t *d_video=sh_video->ds;
demuxer_t *demuxer=d_video->demuxer;
float frame_time=1;
float pts1=d_video->pts;
- float pts=0;
- float fps;
- int picture_coding_type=0;
int in_size=0;
- video_codec_t video_codec = find_video_codec(sh_video);
*start=NULL;
- if(video_codec == VIDEO_MPEG12){
- int in_frame=0;
- //float newfps;
- //videobuf_len=0;
- while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){
- int i=sync_video_packet(d_video);
- //void* buffer=&videobuffer[videobuf_len+4];
- int start=videobuf_len+4;
- if(in_frame){
- if(i<0x101 || i>=0x1B0){ // not slice code -> end of frame
- if(!i) return -1; // EOF
- break;
- }
- } else {
- if(i==0x100){
- pts=d_video->pts;
- d_video->pts=0;
- }
- if(i>=0x101 && i<0x1B0) in_frame=1; // picture startcode
- else if(!i) return -1; // EOF
- }
- if(!read_video_packet(d_video)) return -1; // EOF
- // process headers:
- switch(i){
- case 0x1B3: mp_header_process_sequence_header (&picture, &videobuffer[start]);break;
- case 0x1B5: mp_header_process_extension (&picture, &videobuffer[start]);break;
- case 0x1B2: process_userdata (&videobuffer[start], videobuf_len-start);break;
- case 0x100: picture_coding_type=(videobuffer[start+1] >> 3) & 7;break;
- }
- }
- fps = picture.fps * picture.frame_rate_extension_n / picture.frame_rate_extension_d;
-
- *start=videobuffer; in_size=videobuf_len;
-
- // get mpeg fps:
- if(sh_video->fps!=fps) if(!force_fps && !telecine){
- mp_msg(MSGT_CPLAYER,MSGL_WARN,"Warning! FPS changed %5.3f -> %5.3f (%f) [%d] \n",sh_video->fps,fps,sh_video->fps-fps,picture.frame_rate_code);
- sh_video->fps=fps;
- sh_video->frametime=1.0/fps;
- }
-
- // fix mpeg2 frametime:
- frame_time=(picture.display_time)*0.01f;
- picture.display_time=100;
- videobuf_len=0;
-
- telecine_cnt*=0.9; // drift out error
- telecine_cnt+=frame_time-5.0/4.0;
- mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"\r telecine = %3.1f %5.3f \n",frame_time,telecine_cnt);
-
- if(telecine){
- frame_time=1;
- if(telecine_cnt<-1.5 || telecine_cnt>1.5){
- mp_tmsg(MSGT_DECVIDEO,MSGL_INFO,"\ndemux_mpg: 30000/1001fps NTSC content detected, switching framerate.\n");
- telecine=0;
- }
- } else
- if(telecine_cnt>-0.5 && telecine_cnt<0.5 && !force_fps){
- sh_video->fps=sh_video->fps*4/5;
- sh_video->frametime=sh_video->frametime*5/4;
- mp_tmsg(MSGT_DECVIDEO,MSGL_INFO,"\ndemux_mpg: 24000/1001fps progressive NTSC content detected, switching framerate.\n");
- telecine=1;
- }
- } else if(video_codec == VIDEO_MPEG4){
- while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){
- int i=sync_video_packet(d_video);
- if(!i) return -1;
- if(!read_video_packet(d_video)) return -1; // EOF
- if(i==0x1B6) break;
- }
- *start=videobuffer; in_size=videobuf_len;
- videobuf_len=0;
- } else if(video_codec == VIDEO_H264){
- int in_picture = 0;
- while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){
- int i=sync_video_packet(d_video);
- int pos = videobuf_len+4;
- if(!i) return -1;
- if(!read_video_packet(d_video)) return -1; // EOF
- if((i&~0x60) == 0x107 && i != 0x107) {
- h264_parse_sps(&picture, &(videobuffer[pos]), videobuf_len - pos);
- if(picture.fps > 0) {
- sh_video->fps=picture.fps;
- sh_video->frametime=1.0/picture.fps;
- }
- i=sync_video_packet(d_video);
- if(!i) return -1;
- if(!read_video_packet(d_video)) return -1; // EOF
- }
-
- // here starts the access unit end detection code
- // see the mail on MPlayer-dev-eng for details:
- // Date: Sat, 17 Sep 2005 11:24:06 +0200
- // Subject: Re: [MPlayer-dev-eng] [RFC] h264 ES parser problems
- // Message-ID: <20050917092406.GA7699@rz.uni-karlsruhe.de>
- if((i&~0x60) == 0x101 || (i&~0x60) == 0x102 || (i&~0x60) == 0x105)
- // found VCL NAL with slice header i.e. start of current primary coded
- // picture, so start scanning for the end now
- in_picture = 1;
- if (in_picture) {
- i = sync_video_packet(d_video) & ~0x60; // code of next packet
- if(i == 0x106 || i == 0x109) break; // SEI or access unit delim.
- if(i == 0x101 || i == 0x102 || i == 0x105) {
- // assuming arbitrary slice ordering is not allowed, the
- // first_mb_in_slice (golomb encoded) value should be 0 then
- // for the first VCL NAL in a picture
- if (demux_peekc(d_video) & 0x80)
- break;
- }
- }
- }
- *start=videobuffer; in_size=videobuf_len;
- videobuf_len=0;
- } else if(video_codec == VIDEO_VC1) {
- while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE) {
- int i=sync_video_packet(d_video);
- if(!i) return -1;
- if(!read_video_packet(d_video)) return -1; // EOF
- if(i==0x10D) break;
- }
- *start=videobuffer;
- in_size=videobuf_len;
- videobuf_len=0;
- } else {
// frame-based file formats: (AVI,ASF,MOV)
in_size=ds_get_packet(d_video,start);
if(in_size<0) return -1; // EOF
- }
//------------------------ frame decoded. --------------------
@@ -592,10 +93,7 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char**
frame_time=d_video->pts-pts1;
break;
case DEMUXER_TYPE_TV:
- case DEMUXER_TYPE_MOV:
- case DEMUXER_TYPE_FILM:
case DEMUXER_TYPE_VIVO:
- case DEMUXER_TYPE_OGG:
case DEMUXER_TYPE_ASF: {
double next_pts = ds_get_next_pts(d_video);
double d= (next_pts != MP_NOPTS_VALUE) ? next_pts - d_video->pts : d_video->pts-pts1;
@@ -633,21 +131,8 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char**
break;
}
- if(video_codec == VIDEO_MPEG12){
- sh_video->pts+=frame_time;
- if(picture_coding_type==1)
- d_video->keyframe = true;
- if(picture_coding_type<=2 && sh_video->i_pts){
- sh_video->pts=sh_video->i_pts;
- sh_video->i_pts=pts;
- } else {
- if(pts){
- if(picture_coding_type<=2) sh_video->i_pts=pts;
- else sh_video->pts=pts;
- }
- }
- } else
- sh_video->pts=d_video->pts;
+
+ sh_video->pts=d_video->pts;
if(frame_time_ptr) *frame_time_ptr=frame_time;
return in_size;