aboutsummaryrefslogtreecommitdiffhomepage
path: root/demux
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2013-07-07 23:54:11 +0200
committerGravatar wm4 <wm4@nowhere>2013-07-07 23:54:11 +0200
commitaf0c41e162725b0edcd6c3d066a2dbef05a3b896 (patch)
tree607f2aa997815accec54e838cde124df845c7f38 /demux
parent8781e5a55c5f250e7c637a4cc9c4d8f91b227314 (diff)
Remove old demuxers
Delete demux_avi, demux_asf, demux_mpg, demux_ts. libavformat does better than them (except in rare corner cases), and the demuxers have a bad influence on the rest of the code. Often they don't output proper packets, and require additional audio and video parsing. Most work only in --no-correct-pts mode. Remove them to facilitate further cleanups.
Diffstat (limited to 'demux')
-rw-r--r--demux/asf.h251
-rw-r--r--demux/asfguid.h89
-rw-r--r--demux/asfheader.c721
-rw-r--r--demux/asfheader.h28
-rw-r--r--demux/aviheader.c674
-rw-r--r--demux/aviheader.h382
-rw-r--r--demux/aviprint.c197
-rw-r--r--demux/aviprint.h35
-rw-r--r--demux/demux.c140
-rw-r--r--demux/demux.h71
-rw-r--r--demux/demux_asf.c691
-rw-r--r--demux/demux_avi.c899
-rw-r--r--demux/demux_lavf.c2
-rw-r--r--demux/demux_mkv.c3
-rw-r--r--demux/demux_mpg.c1306
-rw-r--r--demux/demux_ts.c3532
-rw-r--r--demux/demux_ts.h24
-rw-r--r--demux/extension.c25
-rw-r--r--demux/mp3_hdr.c144
-rw-r--r--demux/mp3_hdr.h36
-rw-r--r--demux/mpeg_hdr.c539
-rw-r--r--demux/mpeg_hdr.h55
-rw-r--r--demux/ms_hdr.h8
-rw-r--r--demux/parse_es.c158
-rw-r--r--demux/parse_es.h45
-rw-r--r--demux/stheader.h6
-rw-r--r--demux/video.c527
27 files changed, 26 insertions, 10562 deletions
diff --git a/demux/asf.h b/demux/asf.h
deleted file mode 100644
index db48f72edb..0000000000
--- a/demux/asf.h
+++ /dev/null
@@ -1,251 +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_ASF_H
-#define MPLAYER_ASF_H
-
-#include <sys/types.h>
-#include <inttypes.h>
-#include "libavutil/common.h"
-#include "compat/mpbswap.h"
-
-///////////////////////
-// ASF Object Header
-///////////////////////
-typedef struct __attribute__((packed)) {
- uint8_t guid[16];
- uint64_t size;
-} ASF_obj_header_t;
-
-////////////////
-// ASF Header
-////////////////
-typedef struct __attribute__((packed)) {
- ASF_obj_header_t objh;
- uint32_t cno; // number of subchunks
- uint8_t v1; // unknown (0x01)
- uint8_t v2; // unknown (0x02)
-} ASF_header_t;
-
-/////////////////////
-// ASF File Header
-/////////////////////
-typedef struct __attribute__((packed)) {
- uint8_t stream_id[16]; // stream GUID
- uint64_t file_size;
- uint64_t creation_time; //File creation time FILETIME 8
- uint64_t num_packets; //Number of packets UINT64 8
- uint64_t play_duration; //Timestamp of the end position UINT64 8
- uint64_t send_duration; //Duration of the playback UINT64 8
- uint64_t preroll; //Time to bufferize before playing UINT64 8
- uint32_t flags; //Unknown, maybe flags ( usually contains 2 ) UINT32 4
- uint32_t min_packet_size; //Min size of the packet, in bytes UINT32 4
- uint32_t max_packet_size; //Max size of the packet UINT32 4
- uint32_t max_bitrate; //Maximum bitrate of the media (sum of all the stream)
-} ASF_file_header_t;
-
-///////////////////////
-// ASF Stream Header
-///////////////////////
-typedef struct __attribute__((packed)) {
- uint8_t type[16]; // Stream type (audio/video) GUID 16
- uint8_t concealment[16]; // Audio error concealment type GUID 16
- uint64_t unk1; // Unknown, maybe reserved ( usually contains 0 ) UINT64 8
- uint32_t type_size; //Total size of type-specific data UINT32 4
- uint32_t stream_size; //Size of stream-specific data UINT32 4
- uint16_t stream_no; //Stream number UINT16 2
- uint32_t unk2; //Unknown UINT32 4
-} ASF_stream_header_t;
-
-///////////////////////////
-// ASF Content Description
-///////////////////////////
-typedef struct __attribute__((packed)) {
- uint16_t title_size;
- uint16_t author_size;
- uint16_t copyright_size;
- uint16_t comment_size;
- uint16_t rating_size;
-} ASF_content_description_t;
-
-////////////////////////
-// ASF Segment Header
-////////////////////////
-typedef struct __attribute__((packed)) {
- uint8_t streamno;
- uint8_t seq;
- uint32_t x;
- uint8_t flag;
-} ASF_segmhdr_t;
-
-//////////////////////
-// ASF Stream Chunck
-//////////////////////
-typedef struct __attribute__((packed)) {
- uint16_t type;
- uint16_t size;
- uint32_t sequence_number;
- uint16_t unknown;
- uint16_t size_confirm;
-} ASF_stream_chunck_t;
-
-// Definition of the stream type
-#if BYTE_ORDER == BIG_ENDIAN
- #define ASF_STREAMING_CLEAR 0x2443 // $C
- #define ASF_STREAMING_DATA 0x2444 // $D
- #define ASF_STREAMING_END_TRANS 0x2445 // $E
- #define ASF_STREAMING_HEADER 0x2448 // $H
-#else
- #define ASF_STREAMING_CLEAR 0x4324 // $C
- #define ASF_STREAMING_DATA 0x4424 // $D
- #define ASF_STREAMING_END_TRANS 0x4524 // $E
- #define ASF_STREAMING_HEADER 0x4824 // $H
-#endif
-
-// Definition of the differents type of ASF streaming
-typedef enum {
- ASF_Unknown_e,
- ASF_Live_e,
- ASF_Prerecorded_e,
- ASF_Redirector_e,
- ASF_PlainText_e,
- ASF_Authenticate_e
-} ASF_StreamType_e;
-
-typedef struct {
- ASF_StreamType_e streaming_type;
- int request;
- int packet_size;
- int *audio_streams,n_audio,*video_streams,n_video;
- int audio_id, video_id;
-} asf_http_streaming_ctrl_t;
-
-
-/*
- * Some macros to swap little endian structures read from an ASF file
- * into machine endian format
- */
-#if BYTE_ORDER == BIG_ENDIAN
-#define le2me_ASF_obj_header_t(h) { \
- (h)->size = le2me_64((h)->size); \
-}
-#define le2me_ASF_header_t(h) { \
- le2me_ASF_obj_header_t(&(h)->objh); \
- (h)->cno = le2me_32((h)->cno); \
-}
-#define le2me_ASF_stream_header_t(h) { \
- (h)->unk1 = le2me_64((h)->unk1); \
- (h)->type_size = le2me_32((h)->type_size); \
- (h)->stream_size = le2me_32((h)->stream_size); \
- (h)->stream_no = le2me_16((h)->stream_no); \
- (h)->unk2 = le2me_32((h)->unk2); \
-}
-#define le2me_ASF_file_header_t(h) { \
- (h)->file_size = le2me_64((h)->file_size); \
- (h)->creation_time = le2me_64((h)->creation_time); \
- (h)->num_packets = le2me_64((h)->num_packets); \
- (h)->play_duration = le2me_64((h)->play_duration); \
- (h)->send_duration = le2me_64((h)->send_duration); \
- (h)->preroll = le2me_64((h)->preroll); \
- (h)->flags = le2me_32((h)->flags); \
- (h)->min_packet_size = le2me_32((h)->min_packet_size); \
- (h)->max_packet_size = le2me_32((h)->max_packet_size); \
- (h)->max_bitrate = le2me_32((h)->max_bitrate); \
-}
-#define le2me_ASF_content_description_t(h) { \
- (h)->title_size = le2me_16((h)->title_size); \
- (h)->author_size = le2me_16((h)->author_size); \
- (h)->copyright_size = le2me_16((h)->copyright_size); \
- (h)->comment_size = le2me_16((h)->comment_size); \
- (h)->rating_size = le2me_16((h)->rating_size); \
-}
-#define le2me_BITMAPINFOHEADER(h) { \
- (h)->biSize = le2me_32((h)->biSize); \
- (h)->biWidth = le2me_32((h)->biWidth); \
- (h)->biHeight = le2me_32((h)->biHeight); \
- (h)->biPlanes = le2me_16((h)->biPlanes); \
- (h)->biBitCount = le2me_16((h)->biBitCount); \
- (h)->biCompression = le2me_32((h)->biCompression); \
- (h)->biSizeImage = le2me_32((h)->biSizeImage); \
- (h)->biXPelsPerMeter = le2me_32((h)->biXPelsPerMeter); \
- (h)->biYPelsPerMeter = le2me_32((h)->biYPelsPerMeter); \
- (h)->biClrUsed = le2me_32((h)->biClrUsed); \
- (h)->biClrImportant = le2me_32((h)->biClrImportant); \
-}
-#define le2me_WAVEFORMATEX(h) { \
- (h)->wFormatTag = le2me_16((h)->wFormatTag); \
- (h)->nChannels = le2me_16((h)->nChannels); \
- (h)->nSamplesPerSec = le2me_32((h)->nSamplesPerSec); \
- (h)->nAvgBytesPerSec = le2me_32((h)->nAvgBytesPerSec); \
- (h)->nBlockAlign = le2me_16((h)->nBlockAlign); \
- (h)->wBitsPerSample = le2me_16((h)->wBitsPerSample); \
- (h)->cbSize = le2me_16((h)->cbSize); \
-}
-#define le2me_ASF_stream_chunck_t(h) { \
- (h)->size = le2me_16((h)->size); \
- (h)->sequence_number = le2me_32((h)->sequence_number); \
- (h)->unknown = le2me_16((h)->unknown); \
- (h)->size_confirm = le2me_16((h)->size_confirm); \
-}
-#else
-#define le2me_ASF_obj_header_t(h) /**/
-#define le2me_ASF_header_t(h) /**/
-#define le2me_ASF_stream_header_t(h) /**/
-#define le2me_ASF_file_header_t(h) /**/
-#define le2me_ASF_content_description_t(h) /**/
-#define le2me_BITMAPINFOHEADER(h) /**/
-#define le2me_WAVEFORMATEX(h) /**/
-#define le2me_ASF_stream_chunck_t(h) /**/
-#endif
-
-// priv struct for the demuxer
-struct asf_priv {
- ASF_header_t header;
- unsigned char* packet;
- int scrambling_h;
- int scrambling_w;
- int scrambling_b;
- unsigned packetsize;
- double packetrate;
- double movielength;
- int asf_is_dvr_ms;
- uint32_t asf_frame_state;
- int asf_frame_start_found;
- double dvr_last_vid_pts;
- uint64_t vid_frame_ct;
- uint64_t play_duration;
- uint64_t num_packets;
- int new_vid_frame_seg;
- int *vid_repdata_sizes;
- int *aud_repdata_sizes;
- int vid_repdata_count;
- int aud_repdata_count;
- uint64_t avg_vid_frame_time;
- uint64_t last_key_payload_time;
- uint64_t last_aud_pts;
- uint64_t last_aud_diff;
- int found_first_key_frame;
- uint32_t last_vid_seq;
- int vid_ext_timing_index;
- int aud_ext_timing_index;
- int vid_ext_frame_index;
- int know_frame_time;
- unsigned bps;
-};
-
-#endif /* MPLAYER_ASF_H */
diff --git a/demux/asfguid.h b/demux/asfguid.h
deleted file mode 100644
index e1dfed87d1..0000000000
--- a/demux/asfguid.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2001 Reimar Döffinger
- *
- * 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_ASFGUID_H
-#define MPLAYER_ASFGUID_H
-
-#include <inttypes.h>
-#include "libavutil/common.h"
-#include "compat/mpbswap.h"
-
-
-#define ASF_LOAD_GUID_PREFIX(guid) AV_RL32(guid)
-
-#define ASF_GUID_PREFIX_audio_stream 0xF8699E40
-#define ASF_GUID_PREFIX_video_stream 0xBC19EFC0
-#define ASF_GUID_PREFIX_audio_conceal_none 0x49f1a440
-#define ASF_GUID_PREFIX_audio_conceal_interleave 0xbfc3cd50
-#define ASF_GUID_PREFIX_header 0x75B22630
-#define ASF_GUID_PREFIX_data_chunk 0x75b22636
-#define ASF_GUID_PREFIX_index_chunk 0x33000890
-#define ASF_GUID_PREFIX_stream_header 0xB7DC0791
-#define ASF_GUID_PREFIX_header_2_0 0xD6E229D1
-#define ASF_GUID_PREFIX_file_header 0x8CABDCA1
-#define ASF_GUID_PREFIX_content_desc 0x75b22633
-#define ASF_GUID_PREFIX_stream_group 0x7bf875ce
-#define ASF_GUID_PREFIX_ext_audio_stream 0x31178C9D
-#define ASF_GUID_PREFIX_ext_stream_embed_stream_header 0x3AFB65E2
-#define ASF_GUID_PREFIX_dvr_ms_timing_rep_data 0xFD3CC02A
-#define ASF_GUID_PREFIX_dvr_ms_vid_frame_rep_data 0xDD6432CC
-
-/*
-const char asf_audio_stream_guid[16] = {0x40, 0x9e, 0x69, 0xf8,
- 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b};
-const char asf_video_stream_guid[16] = {0xc0, 0xef, 0x19, 0xbc,
- 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b};
-*/
-static const char asf_stream_header_guid[16] = {0x91, 0x07, 0xdc, 0xb7,
- 0xb7, 0xa9, 0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65};
-static const char asf_file_header_guid[16] = {0xa1, 0xdc, 0xab, 0x8c,
- 0x47, 0xa9, 0xcf, 0x11, 0x8e, 0xe4, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65};
-static const char asf_content_desc_guid[16] = {0x33, 0x26, 0xb2, 0x75,
- 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c};
-static const char asf_stream_group_guid[16] = {0xce, 0x75, 0xf8, 0x7b,
- 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2};
-static const char asf_data_chunk_guid[16] = {0x36, 0x26, 0xb2, 0x75,
- 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c};
-static const char asf_ext_stream_embed_stream_header[16] = {0xe2, 0x65, 0xfb, 0x3a,
- 0xef, 0x47, 0xf2, 0x40, 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43};
-static const char asf_ext_stream_audio[16] = {0x9d, 0x8c, 0x17, 0x31,
- 0xe1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03};
-static const char asf_ext_stream_header[16] = {0xCB, 0xA5, 0xE6, 0x14,
- 0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A};
-static const char asf_metadata_header[16] = {0xea, 0xcb, 0xf8, 0xc5,
- 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, 0xfa, 0x4c, 0xca};
-static const char asf_content_encryption[16] = {0xfb, 0xb3, 0x11, 0x22,
- 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e};
-static const char asf_dvr_ms_timing_rep_data[16] = {0x2a, 0xc0, 0x3c,0xfd,
- 0xdb, 0x06, 0xfa, 0x4c, 0x80, 0x1c, 0x72, 0x12, 0xd3, 0x87, 0x45, 0xe4};
-static const char asf_dvr_ms_vid_frame_rep_data[16] = {0xcc, 0x32, 0x64, 0xdd,
- 0x29, 0xe2, 0xdb, 0x40, 0x80, 0xf6, 0xd2, 0x63, 0x28, 0xd2, 0x76, 0x1f};
-
-static int find_asf_guid(char *buf, const char *guid, int cur_pos, int buf_len)
-{
- int i;
- for (i = cur_pos; i < buf_len - 19; i++) {
- if (memcmp(&buf[i], guid, 16) == 0)
- return i + 16 + 8; // point after guid + length
- }
- return -1;
-}
-
-#endif /* MPLAYER_ASFGUID_H */
diff --git a/demux/asfheader.c b/demux/asfheader.c
deleted file mode 100644
index e3f19840cd..0000000000
--- a/demux/asfheader.c
+++ /dev/null
@@ -1,721 +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.
- */
-
-// .asf fileformat docs from http://divx.euro.ru
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <libavutil/intreadwrite.h>
-#include <libavutil/common.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "aviprint.h"
-#include "demux.h"
-#include "stheader.h"
-
-#include "asf.h"
-#include "asfguid.h"
-#include "asfheader.h"
-
-typedef struct {
- // must be 0 for metadata record, might be non-zero for metadata lib record
- uint16_t lang_list_index;
- uint16_t stream_num;
- uint16_t name_length;
- uint16_t data_type;
- uint32_t data_length;
- uint16_t* name;
- void* data;
-} ASF_meta_record_t;
-
-static char* get_ucs2str(const uint16_t* inbuf, uint16_t inlen)
-{
- char* outbuf = calloc(inlen, 2);
- char* q;
- int i;
-
- if (!outbuf) {
- mp_tmsg(MSGT_HEADER, MSGL_ERR, "Memory allocation failed.\n");
- return NULL;
- }
- q = outbuf;
- for (i = 0; i < inlen / 2; i++) {
- uint8_t tmp;
- PUT_UTF8(AV_RL16(&inbuf[i]), tmp, *q++ = tmp;)
- }
- return outbuf;
-}
-
-static const char* asf_chunk_type(unsigned char* guid) {
- static char tmp[60];
- char *p;
- int i;
-
- switch(ASF_LOAD_GUID_PREFIX(guid)){
- case ASF_GUID_PREFIX_audio_stream:
- return "guid_audio_stream";
- case ASF_GUID_PREFIX_ext_audio_stream:
- return "guid_ext_audio_stream";
- case ASF_GUID_PREFIX_ext_stream_embed_stream_header:
- return "guid_ext_stream_embed_stream_header";
- case ASF_GUID_PREFIX_video_stream:
- return "guid_video_stream";
- case ASF_GUID_PREFIX_audio_conceal_none:
- return "guid_audio_conceal_none";
- case ASF_GUID_PREFIX_audio_conceal_interleave:
- return "guid_audio_conceal_interleave";
- case ASF_GUID_PREFIX_header:
- return "guid_header";
- case ASF_GUID_PREFIX_data_chunk:
- return "guid_data_chunk";
- case ASF_GUID_PREFIX_index_chunk:
- return "guid_index_chunk";
- case ASF_GUID_PREFIX_stream_header:
- return "guid_stream_header";
- case ASF_GUID_PREFIX_header_2_0:
- return "guid_header_2_0";
- case ASF_GUID_PREFIX_file_header:
- return "guid_file_header";
- case ASF_GUID_PREFIX_content_desc:
- return "guid_content_desc";
- case ASF_GUID_PREFIX_dvr_ms_timing_rep_data:
- return "guid_dvr_ms_timing_rep_data";
- case ASF_GUID_PREFIX_dvr_ms_vid_frame_rep_data:
- return "guid_dvr_ms_vid_frame_rep_data";
- default:
- strcpy(tmp, "unknown guid ");
- p = tmp + strlen(tmp);
- for (i = 0; i < 16; i++) {
- if ((1 << i) & ((1<<4) | (1<<6) | (1<<8))) *p++ = '-';
- sprintf(p, "%02x", guid[i]);
- p += 2;
- }
- return tmp;
- }
-}
-
-int asf_check_header(demuxer_t *demuxer){
- unsigned char asfhdrguid[16]={0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C};
- struct asf_priv* asf = calloc(1,sizeof(*asf));
- asf->scrambling_h=asf->scrambling_w=asf->scrambling_b=1;
- stream_read(demuxer->stream,(char*) &asf->header,sizeof(asf->header)); // header obj
- le2me_ASF_header_t(&asf->header); // swap to machine endian
-// for(i=0;i<16;i++) printf(" %02X",temp[i]);printf("\n");
-// for(i=0;i<16;i++) printf(" %02X",asfhdrguid[i]);printf("\n");
- if(memcmp(asfhdrguid,asf->header.objh.guid,16)){
- mp_msg(MSGT_HEADER,MSGL_V,"ASF_check: not ASF guid!\n");
- free(asf);
- return 0; // not ASF guid
- }
- if(asf->header.cno>256){
- mp_msg(MSGT_HEADER,MSGL_V,"ASF_check: invalid subchunks_no %d\n",(int) asf->header.cno);
- free(asf);
- return 0; // invalid header???
- }
- demuxer->priv = asf;
- return DEMUXER_TYPE_ASF;
-}
-
-static int get_ext_stream_properties(char *buf, int buf_len, int stream_num, struct asf_priv* asf, int is_video)
-{
- int pos=0;
- uint8_t *buffer = &buf[0];
- uint64_t avg_ft av_unused;
- unsigned bitrate;
-
- while ((pos = find_asf_guid(buf, asf_ext_stream_header, pos, buf_len)) >= 0) {
- int this_stream_num, stnamect, payct, i;
- int buf_max_index=pos+50;
- if (buf_max_index > buf_len) return 0;
- buffer = &buf[pos];
-
- // the following info is available
- // some of it may be useful but we're skipping it for now
- // starttime(8 bytes), endtime(8),
- // leak-datarate(4), bucket-datasize(4), init-bucket-fullness(4),
- // alt-leak-datarate(4), alt-bucket-datasize(4), alt-init-bucket-fullness(4),
- // max-object-size(4),
- // flags(4) (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
-
- buffer += 8+8;
- bitrate = AV_RL32(buffer);
- buffer += 8*4;
- this_stream_num=AV_RL16(buffer);buffer+=2;
-
- if (this_stream_num == stream_num) {
- buf_max_index+=14;
- if (buf_max_index > buf_len) return 0;
- buffer+=2; //skip stream-language-id-index
- avg_ft = AV_RL64(buffer); // provided in 100ns units
- buffer+=8;
- asf->bps = bitrate / 8;
-
- // after this are values for stream-name-count and
- // payload-extension-system-count
- // followed by associated info for each
- stnamect = AV_RL16(buffer);buffer+=2;
- payct = AV_RL16(buffer);buffer+=2;
-
- // need to read stream names if present in order
- // to get lengths - values are ignored for now
- for (i=0; i<stnamect; i++) {
- int stream_name_len;
- buf_max_index+=4;
- if (buf_max_index > buf_len) return 0;
- buffer+=2; //language_id_index
- stream_name_len = AV_RL16(buffer);buffer+=2;
- buffer+=stream_name_len; //stream_name
- buf_max_index+=stream_name_len;
- if (buf_max_index > buf_len) return 0;
- }
-
- if (is_video) {
- asf->vid_repdata_count = payct;
- asf->vid_repdata_sizes = malloc(payct*sizeof(int));
- } else {
- asf->aud_repdata_count = payct;
- asf->aud_repdata_sizes = malloc(payct*sizeof(int));
- }
-
- for (i=0; i<payct; i++) {
- int payload_len;
- buf_max_index+=22;
- if (buf_max_index > buf_len) return 0;
- // Each payload extension definition starts with a GUID.
- // In dvr-ms files one of these indicates the presence an
- // extension that contains pts values and this is always present
- // in the video and audio streams.
- // Another GUID indicates the presence of an extension
- // that contains useful video frame demuxing information.
- // Note that the extension data in each packet does not contain
- // these GUIDs and that this header section defines the order the data
- // will appear in.
- if (memcmp(buffer, asf_dvr_ms_timing_rep_data, 16) == 0) {
- if (is_video)
- asf->vid_ext_timing_index = i;
- else
- asf->aud_ext_timing_index = i;
- } else if (is_video && memcmp(buffer, asf_dvr_ms_vid_frame_rep_data, 16) == 0)
- asf->vid_ext_frame_index = i;
- buffer+=16;
-
- payload_len = AV_RL16(buffer);buffer+=2;
-
- if (is_video)
- asf->vid_repdata_sizes[i] = payload_len;
- else
- asf->aud_repdata_sizes[i] = payload_len;
- buffer+=4;//sys_len
- }
-
- return 1;
- }
- }
- return 1;
-}
-
-#define CHECKDEC(l, n) if (((l) -= (n)) < 0) return 0
-static char* read_meta_record(ASF_meta_record_t* dest, char* buf,
- int* buf_len)
-{
- CHECKDEC(*buf_len, 2 + 2 + 2 + 2 + 4);
- dest->lang_list_index = AV_RL16(buf);
- dest->stream_num = AV_RL16(&buf[2]);
- dest->name_length = AV_RL16(&buf[4]);
- dest->data_type = AV_RL16(&buf[6]);
- dest->data_length = AV_RL32(&buf[8]);
- buf += 2 + 2 + 2 + 2 + 4;
- CHECKDEC(*buf_len, dest->name_length);
- dest->name = (uint16_t*)buf;
- buf += dest->name_length;
- CHECKDEC(*buf_len, dest->data_length);
- dest->data = buf;
- buf += dest->data_length;
- return buf;
-}
-
-static int get_meta(char *buf, int buf_len, int this_stream_num,
- float* asp_ratio)
-{
- int pos = 0;
- uint16_t records_count;
- uint16_t x = 0, y = 0;
-
- if ((pos = find_asf_guid(buf, asf_metadata_header, pos, buf_len)) < 0)
- return 0;
-
- CHECKDEC(buf_len, pos);
- buf += pos;
- CHECKDEC(buf_len, 2);
- records_count = AV_RL16(buf);
- buf += 2;
-
- while (records_count--) {
- ASF_meta_record_t record_entry;
- char* name;
-
- if (!(buf = read_meta_record(&record_entry, buf, &buf_len)))
- return 0;
- /* reserved, must be zero */
- if (record_entry.lang_list_index)
- continue;
- /* match stream number: 0 to match all */
- if (record_entry.stream_num && record_entry.stream_num != this_stream_num)
- continue;
- if (!(name = get_ucs2str(record_entry.name, record_entry.name_length))) {
- mp_tmsg(MSGT_HEADER, MSGL_ERR, "Memory allocation failed.\n");
- continue;
- }
- if (strcmp(name, "AspectRatioX") == 0)
- x = AV_RL16(record_entry.data);
- else if (strcmp(name, "AspectRatioY") == 0)
- y = AV_RL16(record_entry.data);
- free(name);
- }
- if (x && y) {
- *asp_ratio = (float)x / (float)y;
- return 1;
- }
- return 0;
-}
-
-static int is_drm(char* buf, int buf_len)
-{
- uint32_t data_len, type_len, key_len, url_len;
- int pos = find_asf_guid(buf, asf_content_encryption, 0, buf_len);
-
- if (pos < 0)
- return 0;
-
- CHECKDEC(buf_len, pos + 4);
- buf += pos;
- data_len = AV_RL32(buf);
- buf += 4;
- CHECKDEC(buf_len, data_len);
- buf += data_len;
- type_len = AV_RL32(buf);
- if (type_len < 4)
- return 0;
- CHECKDEC(buf_len, 4 + type_len + 4);
- buf += 4;
-
- if (buf[0] != 'D' || buf[1] != 'R' || buf[2] != 'M' || buf[3] != '\0')
- return 0;
-
- buf += type_len;
- key_len = AV_RL32(buf);
- CHECKDEC(buf_len, key_len + 4);
- buf += 4;
-
- buf[key_len - 1] = '\0';
- mp_msg(MSGT_HEADER, MSGL_V, "DRM Key ID: %s\n", buf);
-
- buf += key_len;
- url_len = AV_RL32(buf);
- CHECKDEC(buf_len, url_len);
- buf += 4;
-
- buf[url_len - 1] = '\0';
- mp_tmsg(MSGT_HEADER, MSGL_INFO, "DRM License URL: %s\n", buf);
- return 1;
-}
-
-static int asf_init_audio_stream(demuxer_t *demuxer,struct asf_priv* asf, sh_audio_t* sh_audio, ASF_stream_header_t *streamh, int *ppos, uint8_t** buf, char *hdr, unsigned int hdr_len)
-{
- uint8_t *buffer = *buf;
- int pos = *ppos;
-
- sh_audio->wf=calloc(FFMAX(streamh->type_size, sizeof(*sh_audio->wf)), 1);
- memcpy(sh_audio->wf,buffer,streamh->type_size);
- le2me_WAVEFORMATEX(sh_audio->wf);
- sh_audio->format=sh_audio->wf->wFormatTag;
- mp_set_audio_codec_from_tag(sh_audio);
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V);
- if(ASF_LOAD_GUID_PREFIX(streamh->concealment)==ASF_GUID_PREFIX_audio_conceal_interleave){
- buffer = &hdr[pos];
- pos += streamh->stream_size;
- if (pos > hdr_len) return 0;
- asf->scrambling_h=buffer[0];
- asf->scrambling_w=(buffer[2]<<8)|buffer[1];
- asf->scrambling_b=(buffer[4]<<8)|buffer[3];
- if(asf->scrambling_b>0){
- asf->scrambling_w/=asf->scrambling_b;
- }
- } else {
- asf->scrambling_b=asf->scrambling_h=asf->scrambling_w=1;
- }
- mp_msg(MSGT_HEADER,MSGL_V,"ASF: audio scrambling: %d x %d x %d\n",asf->scrambling_h,asf->scrambling_w,asf->scrambling_b);
- return 1;
-}
-
-static int find_backwards_asf_guid(char *buf, const char *guid, int cur_pos)
-{
- int i;
- for (i=cur_pos-16; i>0; i--) {
- if (memcmp(&buf[i], guid, 16) == 0)
- return i + 16 + 8; // point after guid + length
- }
- return -1;
-}
-
-int read_asf_header(demuxer_t *demuxer,struct asf_priv* asf){
- int hdr_len = asf->header.objh.size - sizeof(asf->header);
- int hdr_skip = 0;
- char *hdr = NULL;
- char guid_buffer[16];
- int pos, start = stream_tell(demuxer->stream);
- uint32_t* streams = NULL;
- int audio_streams=0;
- int video_streams=0;
- uint16_t stream_count=0;
- int best_video = -1;
- int best_audio = -1;
- uint64_t data_len;
- ASF_stream_header_t *streamh;
- uint8_t *buffer;
- int audio_pos=0;
-
- if(hdr_len < 0) {
- mp_msg(MSGT_HEADER, MSGL_FATAL, "Header size is too small.\n");
- return 0;
- }
-
- if (hdr_len > 1024 * 1024) {
- mp_tmsg(MSGT_HEADER, MSGL_ERR, "FATAL: header size bigger than 1 MB (%d)!\nPlease contact MPlayer authors, and upload/send this file.\n",
- hdr_len);
- hdr_skip = hdr_len - 1024 * 1024;
- hdr_len = 1024 * 1024;
- }
- hdr = malloc(hdr_len);
- if (!hdr) {
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "Could not allocate %d bytes for header.\n",
- hdr_len);
- return 0;
- }
- stream_read(demuxer->stream, hdr, hdr_len);
- if (hdr_skip)
- stream_skip(demuxer->stream, hdr_skip);
- if (stream_eof(demuxer->stream)) {
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "EOF while reading ASF header, broken/incomplete file?\n");
- goto err_out;
- }
-
- if (is_drm(hdr, hdr_len))
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "This file has been encumbered with DRM encryption, it will not play in MPlayer!\n");
-
- if ((pos = find_asf_guid(hdr, asf_ext_stream_audio, 0, hdr_len)) >= 0)
- {
- // Special case: found GUID for dvr-ms audio.
- // Now skip back to associated stream header.
- int sh_pos=0;
-
- sh_pos = find_backwards_asf_guid(hdr, asf_stream_header_guid, pos);
-
- if (sh_pos > 0) {
- sh_audio_t *sh_audio;
-
- mp_msg(MSGT_HEADER, MSGL_V, "read_asf_header found dvr-ms audio stream header pos=%d\n", sh_pos);
- // found audio stream header - following code reads header and
- // initializes audio stream.
- audio_pos = pos - 16 - 8;
- streamh = (ASF_stream_header_t *)&hdr[sh_pos];
- le2me_ASF_stream_header_t(streamh);
- audio_pos += 64; //16+16+4+4+4+16+4;
- buffer = &hdr[audio_pos];
- sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F);
- sh_audio->needs_parsing = 1;
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "asfheader", streamh->stream_no & 0x7F);
- ++audio_streams;
- if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &audio_pos, &buffer, hdr, hdr_len))
- goto len_err_out;
- if (!get_ext_stream_properties(hdr, hdr_len, streamh->stream_no, asf, 0))
- goto len_err_out;
- }
- }
- // find stream headers
- // only reset pos if we didnt find dvr_ms audio stream
- // if we did find it then we want to avoid reading its header twice
- if (audio_pos == 0)
- pos = 0;
-
- while ((pos = find_asf_guid(hdr, asf_stream_header_guid, pos, hdr_len)) >= 0)
- {
- streamh = (ASF_stream_header_t *)&hdr[pos];
- pos += sizeof(ASF_stream_header_t);
- if (pos > hdr_len) goto len_err_out;
- le2me_ASF_stream_header_t(streamh);
- mp_msg(MSGT_HEADER, MSGL_V, "stream type: %s\n",
- asf_chunk_type(streamh->type));
- mp_msg(MSGT_HEADER, MSGL_V, "stream concealment: %s\n",
- asf_chunk_type(streamh->concealment));
- mp_msg(MSGT_HEADER, MSGL_V, "type: %d bytes, stream: %d bytes ID: %d\n",
- (int)streamh->type_size, (int)streamh->stream_size,
- (int)streamh->stream_no);
- mp_msg(MSGT_HEADER, MSGL_V, "unk1: %lX unk2: %X\n",
- (unsigned long)streamh->unk1, (unsigned int)streamh->unk2);
- mp_msg(MSGT_HEADER, MSGL_V, "FILEPOS=0x%X\n", pos + start);
- // type-specific data:
- buffer = &hdr[pos];
- pos += streamh->type_size;
- if (pos > hdr_len) goto len_err_out;
- switch(ASF_LOAD_GUID_PREFIX(streamh->type)){
- case ASF_GUID_PREFIX_audio_stream: {
- sh_audio_t* sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "asfheader", streamh->stream_no & 0x7F);
- ++audio_streams;
- if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &pos, &buffer, hdr, hdr_len))
- goto len_err_out;
- //if(demuxer->audio->id==-1) demuxer->audio->id=streamh.stream_no & 0x7F;
- break;
- }
- case ASF_GUID_PREFIX_video_stream: {
- unsigned int len;
- float asp_ratio;
- sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Video stream found, -vid %d\n", "asfheader", streamh->stream_no & 0x7F);
- len=streamh->type_size-(4+4+1+2);
- ++video_streams;
-// sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize);
- sh_video->bih=calloc((len<sizeof(*sh_video->bih))?sizeof(*sh_video->bih):len,1);
- memcpy(sh_video->bih,&buffer[4+4+1+2],len);
- le2me_BITMAPINFOHEADER(sh_video->bih);
- if (sh_video->bih->biSize > len && sh_video->bih->biSize > sizeof(*sh_video->bih))
- sh_video->bih->biSize = len;
- if (sh_video->bih->biCompression == mmioFOURCC('D', 'V', 'R', ' ')) {
- //mp_tmsg(MSGT_DEMUXER, MSGL_WARN, "DVR will probably only work with libavformat, try -demuxer 35 if you have problems\n");
- //sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
- //sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
- asf->asf_frame_state=-1;
- asf->asf_frame_start_found=0;
- asf->asf_is_dvr_ms=1;
- asf->dvr_last_vid_pts=0.0;
- } else asf->asf_is_dvr_ms=0;
- if (!get_ext_stream_properties(hdr, hdr_len, streamh->stream_no, asf, 1))
- goto len_err_out;
- if (get_meta(hdr, hdr_len, streamh->stream_no, &asp_ratio)) {
- sh_video->aspect = asp_ratio * sh_video->bih->biWidth /
- sh_video->bih->biHeight;
- }
- sh_video->i_bps = asf->bps;
- sh_video->format = sh_video->bih->biCompression;
- mp_set_video_codec_from_tag(sh_video);
- sh_video->format = mp_video_fourcc_alias(sh_video->format);
-
- if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V);
- //asf_video_id=streamh.stream_no & 0x7F;
- //if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F;
- break;
- }
- }
- // stream-specific data:
- // stream_read(demuxer->stream,(char*) buffer,streamh.stream_size);
- }
-
- // find file header
- pos = find_asf_guid(hdr, asf_file_header_guid, 0, hdr_len);
- if (pos >= 0) {
- ASF_file_header_t *fileh = (ASF_file_header_t *)&hdr[pos];
- pos += sizeof(ASF_file_header_t);
- if (pos > hdr_len) goto len_err_out;
- le2me_ASF_file_header_t(fileh);
- mp_msg(MSGT_HEADER, MSGL_V, "ASF: packets: %d flags: %d "
- "max_packet_size: %d min_packet_size: %d max_bitrate: %d "
- "preroll: %d\n",
- (int)fileh->num_packets, (int)fileh->flags,
- (int)fileh->min_packet_size, (int)fileh->max_packet_size,
- (int)fileh->max_bitrate, (int)fileh->preroll);
- asf->packetsize=fileh->max_packet_size;
- asf->packet=malloc(asf->packetsize); // !!!
- asf->packetrate=fileh->max_bitrate/8.0/(double)asf->packetsize;
- asf->movielength=FFMAX(0.0, (fileh->play_duration / 10000.0 - fileh->preroll) / 1000.0);
- }
-
- // find content header
- pos = find_asf_guid(hdr, asf_content_desc_guid, 0, hdr_len);
- if (pos >= 0) {
- ASF_content_description_t *contenth = (ASF_content_description_t *)&hdr[pos];
- char *string=NULL;
- uint16_t* wstring = NULL;
- uint16_t len;
- pos += sizeof(ASF_content_description_t);
- if (pos > hdr_len) goto len_err_out;
- le2me_ASF_content_description_t(contenth);
- mp_msg(MSGT_HEADER,MSGL_V,"\n");
- // extract the title
- if((len = contenth->title_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Title: %s\n", string);
- demux_info_add(demuxer, "title", string);
- free(string);
- }
- }
- // extract the author
- if((len = contenth->author_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Author: %s\n", string);
- demux_info_add(demuxer, "author", string);
- free(string);
- }
- }
- // extract the copyright
- if((len = contenth->copyright_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Copyright: %s\n", string);
- demux_info_add(demuxer, "copyright", string);
- free(string);
- }
- }
- // extract the comment
- if((len = contenth->comment_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Comment: %s\n", string);
- demux_info_add(demuxer, "comments", string);
- free(string);
- }
- }
- // extract the rating
- if((len = contenth->rating_size) != 0) {
- wstring = (uint16_t*)&hdr[pos];
- pos += len;
- if (pos > hdr_len) goto len_err_out;
- if ((string = get_ucs2str(wstring, len))) {
- mp_msg(MSGT_HEADER,MSGL_V," Rating: %s\n", string);
- free(string);
- }
- }
- mp_msg(MSGT_HEADER,MSGL_V,"\n");
- }
-
- // find content header
- pos = find_asf_guid(hdr, asf_stream_group_guid, 0, hdr_len);
- if (pos >= 0) {
- int max_streams = (hdr_len - pos - 2) / 6;
- uint16_t stream_id, i;
- uint32_t max_bitrate;
- char *ptr = &hdr[pos];
- mp_msg(MSGT_HEADER,MSGL_V,"============ ASF Stream group == START ===\n");
- if(max_streams <= 0) goto len_err_out;
- stream_count = AV_RL16(ptr);
- ptr += sizeof(uint16_t);
- if(stream_count > max_streams) stream_count = max_streams;
- if(stream_count > 0)
- streams = malloc(2*stream_count*sizeof(uint32_t));
- mp_msg(MSGT_HEADER,MSGL_V," stream count=[0x%x][%u]\n", stream_count, stream_count );
- for( i=0 ; i<stream_count ; i++ ) {
- stream_id = AV_RL16(ptr);
- ptr += sizeof(uint16_t);
- max_bitrate = AV_RL32(ptr);
- ptr += sizeof(uint32_t);
- mp_msg(MSGT_HEADER,MSGL_V," stream id=[0x%x][%u]\n", stream_id, stream_id );
- mp_msg(MSGT_HEADER,MSGL_V," max bitrate=[0x%x][%u]\n", max_bitrate, max_bitrate );
- streams[2*i] = stream_id;
- streams[2*i+1] = max_bitrate;
- }
- mp_msg(MSGT_HEADER,MSGL_V,"============ ASF Stream group == END ===\n");
- }
- free(hdr);
- hdr = NULL;
- start = stream_tell(demuxer->stream); // start of first data chunk
- stream_read(demuxer->stream, guid_buffer, 16);
- if (memcmp(guid_buffer, asf_data_chunk_guid, 16) != 0) {
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "No data chunk following header!\n");
- free(streams);
- streams = NULL;
- return 0;
- }
- // read length of chunk
- data_len = stream_read_qword_le(demuxer->stream);
- demuxer->movi_start = stream_tell(demuxer->stream) + 26;
- demuxer->movi_end = start + data_len;
- mp_msg(MSGT_HEADER, MSGL_V, "Found movie at 0x%X - 0x%X\n",
- (int)demuxer->movi_start, (int)demuxer->movi_end);
-
-if(streams) {
- // stream selection is done in the network code, it shouldn't be done here
- // as the servers often do not care about what we requested.
-#if 0
- uint32_t vr = 0, ar = 0,i;
-#ifdef CONFIG_NETWORKING
- if( demuxer->stream->streaming_ctrl!=NULL ) {
- if( demuxer->stream->streaming_ctrl->bandwidth!=0 && demuxer->stream->streaming_ctrl->data!=NULL ) {
- best_audio = ((asf_http_streaming_ctrl_t*)demuxer->stream->streaming_ctrl->data)->audio_id;
- best_video = ((asf_http_streaming_ctrl_t*)demuxer->stream->streaming_ctrl->data)->video_id;
- }
- } else
-#endif
- for(i = 0; i < stream_count; i++) {
- uint32_t id = streams[2*i];
- uint32_t rate = streams[2*i+1];
- if(demuxer->v_streams[id] && rate > vr) {
- vr = rate;
- best_video = id;
- } else if(demuxer->a_streams[id] && rate > ar) {
- ar = rate;
- best_audio = id;
- }
- }
-#endif
- free(streams);
- streams = NULL;
-}
-
-mp_msg(MSGT_HEADER,MSGL_V,"ASF: %d audio and %d video streams found\n",audio_streams,video_streams);
-if(!audio_streams) demuxer->audio->id=-2; // nosound
-else if(best_audio > 0 && demuxer->audio->id == -1) demuxer->audio->id=best_audio;
-if(!video_streams){
- if(!audio_streams){
- mp_tmsg(MSGT_HEADER,MSGL_ERR,"ASF: no audio or video headers found - broken file?\n");
- return 0;
- }
- demuxer->video->id=-2; // audio-only
-} else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video;
-
-#if 0
-if( mp_msg_test(MSGT_HEADER,MSGL_V) ){
- printf("ASF duration: %d\n",(int)fileh.duration);
- printf("ASF start pts: %d\n",(int)fileh.start_timestamp);
- printf("ASF end pts: %d\n",(int)fileh.end_timestamp);
-}
-#endif
-
-return 1;
-
-len_err_out:
- mp_tmsg(MSGT_HEADER, MSGL_FATAL, "Invalid length in ASF header!\n");
-err_out:
- free(hdr);
- free(streams);
- return 0;
-}
diff --git a/demux/asfheader.h b/demux/asfheader.h
deleted file mode 100644
index 3741f22cd6..0000000000
--- a/demux/asfheader.h
+++ /dev/null
@@ -1,28 +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_ASFHEADER_H
-#define MPLAYER_ASFHEADER_H
-
-#include "asf.h"
-#include "demux.h"
-
-int asf_check_header(demuxer_t *demuxer);
-int read_asf_header(demuxer_t *demuxer, struct asf_priv *asf);
-
-#endif /* MPLAYER_ASFHEADER_H */
diff --git a/demux/aviheader.c b/demux/aviheader.c
deleted file mode 100644
index c1b9c59692..0000000000
--- a/demux/aviheader.c
+++ /dev/null
@@ -1,674 +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 <unistd.h>
-#include <errno.h>
-
-#include <libavutil/common.h>
-#include <libavutil/intreadwrite.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "demux.h"
-#include "stheader.h"
-#include "aviprint.h"
-#include "aviheader.h"
-
-static MainAVIHeader avih;
-
-static int odml_get_vstream_id(int id, unsigned char res[])
-{
- if ((char)(id >> 16) == 'd') {
- if (res) {
- res[0] = id;
- res[1] = id >> 8;
- }
- return 1;
- }
- return 0;
-}
-
-static int avi_idx_cmp(const void *elem1, const void *elem2)
-{
- register int64_t a = AVI_IDX_OFFSET((AVIINDEXENTRY *)elem1);
- register int64_t b = AVI_IDX_OFFSET((AVIINDEXENTRY *)elem2);
- return (a > b) - (b > a);
-}
-
-void read_avi_header(demuxer_t *demuxer,int index_mode){
-sh_audio_t *sh_audio=NULL;
-sh_video_t *sh_video=NULL;
-int stream_id=-1;
-int idxfix_videostream=0;
-int idxfix_divx=0;
-avi_priv_t* priv=demuxer->priv;
-int64_t list_end=0;
-
-//---- AVI header:
-priv->idx_size=0;
-priv->audio_streams=0;
-while(1){
- int id=stream_read_dword_le(demuxer->stream);
- unsigned chunksize,size2;
- static int last_fccType=0;
- static int last_fccHandler=0;
- char* hdr=NULL;
- //
- if(stream_eof(demuxer->stream)) break;
- //
- if(id==mmioFOURCC('L','I','S','T')){
- unsigned len=stream_read_dword_le(demuxer->stream); // list size
- id=stream_read_dword_le(demuxer->stream); // list type
- mp_msg(MSGT_HEADER,MSGL_DBG2,"LIST %.4s len=%u\n",(char *) &id,len);
- if(len >= 4) {
- len -= 4;
- list_end=stream_tell(demuxer->stream)+((len+1)&(~1));
- } else {
- mp_tmsg(MSGT_HEADER,MSGL_WARN,"** empty list?!\n");
- list_end = 0;
- }
- mp_msg(MSGT_HEADER,MSGL_V,"list_end=0x%X\n",(int)list_end);
- if(id==listtypeAVIMOVIE){
- // found MOVI header
- if(!demuxer->movi_start) demuxer->movi_start=stream_tell(demuxer->stream);
- demuxer->movi_end=stream_tell(demuxer->stream)+len;
- mp_tmsg(MSGT_HEADER,MSGL_V,"Found movie at 0x%X - 0x%X\n",(int)demuxer->movi_start,(int)demuxer->movi_end);
- if(demuxer->stream->end_pos>demuxer->movi_end) demuxer->movi_end=demuxer->stream->end_pos;
- if(index_mode==-2 || index_mode==2 || index_mode==0)
- break; // reading from non-seekable source (stdin) or forced index or no index forced
- if(list_end>0) stream_seek(demuxer->stream,list_end); // skip movi
- list_end=0;
- }
- continue;
- }
- size2=stream_read_dword_le(demuxer->stream);
- mp_msg(MSGT_HEADER,MSGL_DBG2,"CHUNK %.4s len=%u\n",(char *) &id,size2);
- chunksize=(size2+1)&(~1);
- switch(id){
-
- // Indicates where the subject of the file is archived
- case mmioFOURCC('I','A','R','L'): hdr="Archival Location";break;
- // Lists the artist of the original subject of the file;
- // for example, "Michaelangelo."
- case mmioFOURCC('I','A','R','T'): hdr="Artist";break;
- // Lists the name of the person or organization that commissioned
- // the subject of the file; for example "Pope Julian II."
- case mmioFOURCC('I','C','M','S'): hdr="Commissioned";break;
- // Provides general comments about the file or the subject
- // of the file. If the comment is several sentences long, end each
- // sentence with a period. Do not include new-line characters.
- case mmioFOURCC('I','C','M','T'): hdr="Comments";break;
- // Records the copyright information for the file; for example,
- // "Copyright Encyclopedia International 1991." If there are multiple
- // copyrights, separate them by semicolon followed by a space.
- case mmioFOURCC('I','C','O','P'): hdr="Copyright";break;
- // Describes whether an image has been cropped and, if so, how it
- // was cropped; for example, "lower-right corner."
- case mmioFOURCC('I','C','R','D'): hdr="Creation Date";break;
- // Describes whether an image has been cropped and, if so, how it
- // was cropped; for example, "lower-right corner."
- case mmioFOURCC('I','C','R','P'): hdr="Cropped";break;
- // Specifies the size of the original subject of the file; for
- // example, "8.5 in h, 11 in w."
- case mmioFOURCC('I','D','I','M'): hdr="Dimensions";break;
- // Stores dots per inch setting of the digitizer used to
- // produce the file, such as "300."
- case mmioFOURCC('I','D','P','I'): hdr="Dots Per Inch";break;
- // Stores the of the engineer who worked on the file. If there are
- // multiple engineers, separate the names by a semicolon and a blank;
- // for example, "Smith, John; Adams, Joe."
- case mmioFOURCC('I','E','N','G'): hdr="Engineer";break;
- // Describes the original work, such as "landscape,", "portrait,"
- // "still liefe," etc.
- case mmioFOURCC('I','G','N','R'): hdr="Genre";break;
- // Provides a list of keywords that refer to the file or subject of the
- // file. Separate multiple keywords with a semicolon and a blank;
- // for example, "Seattle, aerial view; scenery."
- case mmioFOURCC('I','K','E','Y'): hdr="Keywords";break;
- // ILGT - Describes the changes in the lightness settings on the digitizer
- // required to produce the file. Note that the format of this information
- // depends on the hardware used.
- case mmioFOURCC('I','L','G','T'): hdr="Lightness";break;
- // IMED - Decribes the original subject of the file, such as
- // "computer image," "drawing," "lithograph," and so on.
- case mmioFOURCC('I','M','E','D'): hdr="Medium";break;
- // INAM - Stores the title of the subject of the file, such as
- // "Seattle from Above."
- case mmioFOURCC('I','N','A','M'): hdr="Title";break;
- // IPLT - Specifies the number of colors requested when digitizing
- // an image, such as "256."
- case mmioFOURCC('I','P','L','T'): hdr="Palette Setting";break;
- // IPRD - Specifies the name of title the file was originally intended
- // for, such as "Encyclopedia of Pacific Northwest Geography."
- case mmioFOURCC('I','P','R','D'): hdr="Product";break;
- // ISBJ - Decsribes the contents of the file, such as
- // "Aerial view of Seattle."
- case mmioFOURCC('I','S','B','J'): hdr="Subject";break;
- // ISFT - Identifies the name of the software packages used to create the
- // file, such as "Microsoft WaveEdit"
- case mmioFOURCC('I','S','F','T'): hdr="Software";break;
- // ISHP - Identifies the change in sharpness for the digitizer
- // required to produce the file (the format depends on the hardware used).
- case mmioFOURCC('I','S','H','P'): hdr="Sharpness";break;
- // ISRC - Identifies the name of the person or organization who
- // supplied the original subject of the file; for example, "Try Research."
- case mmioFOURCC('I','S','R','C'): hdr="Source";break;
- // ISRF - Identifies the original form of the material that was digitized,
- // such as "slide," "paper," "map," and so on. This is not necessarily
- // the same as IMED
- case mmioFOURCC('I','S','R','F'): hdr="Source Form";break;
- // ITCH - Identifies the technician who digitized the subject file;
- // for example, "Smith, John."
- case mmioFOURCC('I','T','C','H'): hdr="Technician";break;
- case mmioFOURCC('I','S','M','P'): hdr="Time Code";break;
- case mmioFOURCC('I','D','I','T'): hdr="Digitization Time";break;
-
- case ckidAVIMAINHDR: // read 'avih'
- stream_read(demuxer->stream,(char*) &avih,FFMIN(size2,sizeof(avih)));
- le2me_MainAVIHeader(&avih); // swap to machine endian
- chunksize-=FFMIN(size2,sizeof(avih));
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_avih(&avih,MSGL_V); // else print_avih_flags(&avih,MSGL_V);
- break;
- case ckidSTREAMHEADER: { // read 'strh'
- AVIStreamHeader h;
- stream_read(demuxer->stream,(char*) &h,FFMIN(size2,sizeof(h)));
- le2me_AVIStreamHeader(&h); // swap to machine endian
- chunksize-=FFMIN(size2,sizeof(h));
- ++stream_id;
- if(h.fccType==streamtypeVIDEO){
- sh_video=new_sh_video(demuxer,stream_id);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Video stream found, -vid %d\n", "aviheader", stream_id);
- memcpy(&sh_video->video,&h,sizeof(h));
- sh_video->stream_delay = (float)sh_video->video.dwStart * sh_video->video.dwScale/sh_video->video.dwRate;
- } else
- if(h.fccType==streamtypeAUDIO){
- sh_audio=new_sh_audio(demuxer,stream_id);
- mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[%s] Audio stream found, -aid %d\n", "aviheader", stream_id);
- memcpy(&sh_audio->audio,&h,sizeof(h));
- sh_audio->stream_delay = (float)sh_audio->audio.dwStart * sh_audio->audio.dwScale/sh_audio->audio.dwRate;
- sh_audio->needs_parsing = 1;
- }
- last_fccType=h.fccType;
- last_fccHandler=h.fccHandler;
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_strh(&h,MSGL_V);
- break; }
- case mmioFOURCC('i', 'n', 'd', 'x'): {
- uint32_t i;
- avisuperindex_chunk *s;
-
- if(!index_mode) break;
-
- if(chunksize<=24){
- break;
- }
- priv->suidx_size++;
- priv->suidx = realloc_struct(priv->suidx, priv->suidx_size, sizeof (avisuperindex_chunk));
- s = &priv->suidx[priv->suidx_size-1];
-
- chunksize-=24;
- memcpy(s->fcc, "indx", 4);
- s->dwSize = size2;
- s->wLongsPerEntry = stream_read_word_le(demuxer->stream);
- s->bIndexSubType = stream_read_char(demuxer->stream);
- s->bIndexType = stream_read_char(demuxer->stream);
- s->nEntriesInUse = stream_read_dword_le(demuxer->stream);
- AV_WN32(s->dwChunkId, stream_read_dword_le(demuxer->stream));
- stream_read(demuxer->stream, (char *)s->dwReserved, 3*4);
- memset(s->dwReserved, 0, 3*4);
-
- print_avisuperindex_chunk(s,MSGL_V);
-
- // Check and fix this useless crap
- if(s->wLongsPerEntry != sizeof (avisuperindex_entry)/4) {
- mp_msg (MSGT_HEADER, MSGL_WARN, "Broken super index chunk size: %u\n",s->wLongsPerEntry);
- s->wLongsPerEntry = sizeof(avisuperindex_entry)/4;
- }
- if( ((chunksize/4)/s->wLongsPerEntry) < s->nEntriesInUse){
- mp_msg (MSGT_HEADER, MSGL_WARN, "Broken super index chunk\n");
- s->nEntriesInUse = (chunksize/4)/s->wLongsPerEntry;
- }
-
- s->aIndex = calloc(s->nEntriesInUse, sizeof (avisuperindex_entry));
- s->stdidx = calloc(s->nEntriesInUse, sizeof (avistdindex_chunk));
-
- // now the real index of indices
- for (i=0; i<s->nEntriesInUse; i++) {
- chunksize-=16;
- s->aIndex[i].qwOffset = stream_read_qword_le(demuxer->stream);
- s->aIndex[i].dwSize = stream_read_dword_le(demuxer->stream);
- s->aIndex[i].dwDuration = stream_read_dword_le(demuxer->stream);
- mp_msg (MSGT_HEADER, MSGL_V, "ODML (%.4s): [%d] 0x%016"PRIx64" 0x%04x %u\n",
- s->dwChunkId, i,
- (uint64_t)s->aIndex[i].qwOffset, s->aIndex[i].dwSize, s->aIndex[i].dwDuration);
- }
-
- break; }
- case ckidSTREAMFORMAT: { // read 'strf'
- if(last_fccType==streamtypeVIDEO){
- sh_video->bih=calloc(FFMAX(chunksize, sizeof(*sh_video->bih)), 1);
-// sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize);
- mp_tmsg(MSGT_HEADER,MSGL_V,"Found 'bih', %u bytes of %zu\n",chunksize,sizeof(*sh_video->bih));
- stream_read(demuxer->stream,(char*) sh_video->bih,chunksize);
- le2me_BITMAPINFOHEADER(sh_video->bih); // swap to machine endian
- if (sh_video->bih->biSize > chunksize && sh_video->bih->biSize > sizeof(*sh_video->bih))
- sh_video->bih->biSize = chunksize;
- // fixup MS-RLE header (seems to be broken for <256 color files)
- if(sh_video->bih->biCompression<=1 && sh_video->bih->biSize==40)
- sh_video->bih->biSize=chunksize;
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih,MSGL_V);
- chunksize=0;
- sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
- sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
- sh_video->format = sh_video->bih->biCompression;
- mp_set_video_codec_from_tag(sh_video);
- sh_video->format = mp_video_fourcc_alias(sh_video->format);
-// if(demuxer->video->id==-1) demuxer->video->id=stream_id;
- // IdxFix:
- idxfix_videostream=stream_id;
- switch(sh_video->bih->biCompression){
- case mmioFOURCC('M', 'P', 'G', '4'):
- case mmioFOURCC('m', 'p', 'g', '4'):
- case mmioFOURCC('D', 'I', 'V', '1'):
- idxfix_divx=3; // set index recovery mpeg4 flavour: msmpeg4v1
- mp_tmsg(MSGT_HEADER,MSGL_V,"Regenerating keyframe table for M$ mpg4v1 video.\n");
- break;
- case mmioFOURCC('D', 'I', 'V', '3'):
- case mmioFOURCC('d', 'i', 'v', '3'):
- case mmioFOURCC('D', 'I', 'V', '4'):
- case mmioFOURCC('d', 'i', 'v', '4'):
- case mmioFOURCC('D', 'I', 'V', '5'):
- case mmioFOURCC('d', 'i', 'v', '5'):
- case mmioFOURCC('D', 'I', 'V', '6'):
- case mmioFOURCC('d', 'i', 'v', '6'):
- case mmioFOURCC('M', 'P', '4', '3'):
- case mmioFOURCC('m', 'p', '4', '3'):
- case mmioFOURCC('M', 'P', '4', '2'):
- case mmioFOURCC('m', 'p', '4', '2'):
- case mmioFOURCC('D', 'I', 'V', '2'):
- case mmioFOURCC('A', 'P', '4', '1'):
- idxfix_divx=1; // set index recovery mpeg4 flavour: msmpeg4v3
- mp_tmsg(MSGT_HEADER,MSGL_V,"Regenerating keyframe table for DIVX3 video.\n");
- break;
- case mmioFOURCC('D', 'I', 'V', 'X'):
- case mmioFOURCC('d', 'i', 'v', 'x'):
- case mmioFOURCC('D', 'X', '5', '0'):
- case mmioFOURCC('X', 'V', 'I', 'D'):
- case mmioFOURCC('x', 'v', 'i', 'd'):
- case mmioFOURCC('F', 'M', 'P', '4'):
- case mmioFOURCC('f', 'm', 'p', '4'):
- idxfix_divx=2; // set index recovery mpeg4 flavour: generic mpeg4
- mp_tmsg(MSGT_HEADER,MSGL_V,"Regenerating keyframe table for MPEG-4 video.\n");
- break;
- }
- } else
- if(last_fccType==streamtypeAUDIO){
- unsigned wf_size = chunksize<sizeof(*sh_audio->wf)?sizeof(*sh_audio->wf):chunksize;
- sh_audio->wf=calloc(wf_size,1);
-// sh_audio->wf=malloc(chunksize); memset(sh_audio->wf,0,chunksize);
- mp_tmsg(MSGT_HEADER,MSGL_V,"Found 'wf', %d bytes of %zu\n",chunksize,sizeof(*sh_audio->wf));
- stream_read(demuxer->stream,(char*) sh_audio->wf,chunksize);
- le2me_WAVEFORMATEX(sh_audio->wf);
- if (sh_audio->wf->cbSize != 0 &&
- wf_size < sizeof(*sh_audio->wf)+sh_audio->wf->cbSize) {
- sh_audio->wf=realloc(sh_audio->wf, sizeof(*sh_audio->wf)+sh_audio->wf->cbSize);
- }
- sh_audio->format=sh_audio->wf->wFormatTag;
- if (sh_audio->wf->wFormatTag == 0xfffe && sh_audio->wf->cbSize >= 22)
- sh_audio->format = le2me_16(((WAVEFORMATEXTENSIBLE *)sh_audio->wf)->SubFormat);
- if (sh_audio->format == 1 &&
- last_fccHandler == mmioFOURCC('A', 'x', 'a', 'n'))
- sh_audio->format = last_fccHandler;
- mp_set_audio_codec_from_tag(sh_audio);
- sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec;
- chunksize=0;
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V);
- ++priv->audio_streams;
-// if(demuxer->audio->id==-1) demuxer->audio->id=stream_id;
- }
- break;
- }
- case mmioFOURCC('v', 'p', 'r', 'p'): {
- VideoPropHeader *vprp = malloc(chunksize);
- unsigned int i;
- stream_read(demuxer->stream, (void*)vprp, chunksize);
- le2me_VideoPropHeader(vprp);
- chunksize -= sizeof(*vprp)-sizeof(vprp->FieldInfo);
- chunksize /= sizeof(VIDEO_FIELD_DESC);
- if (vprp->nbFieldPerFrame > chunksize) {
- vprp->nbFieldPerFrame = chunksize;
- }
- chunksize = 0;
- for (i=0; i<vprp->nbFieldPerFrame; i++) {
- le2me_VIDEO_FIELD_DESC(&vprp->FieldInfo[i]);
- }
- if (sh_video) {
- sh_video->aspect = GET_AVI_ASPECT(vprp->dwFrameAspectRatio);
- }
- if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_vprp(vprp,MSGL_V);
- free(vprp);
- break;
- }
- case mmioFOURCC('d', 'm', 'l', 'h'): {
- // dmlh 00 00 00 04 frms
- unsigned int total_frames = stream_read_dword_le(demuxer->stream);
- mp_tmsg(MSGT_HEADER,MSGL_V,"AVI: dmlh found (size=%d) (total_frames=%d)\n", chunksize, total_frames);
- stream_skip(demuxer->stream, chunksize-4);
- chunksize = 0;
- }
- break;
- case ckidAVINEWINDEX:
- if(demuxer->movi_end>stream_tell(demuxer->stream))
- demuxer->movi_end=stream_tell(demuxer->stream); // fixup movi-end
- if(index_mode && !priv->isodml){
- int read;
- int i;
- priv->idx_size=size2>>4;
- mp_tmsg(MSGT_HEADER,MSGL_V,"Reading INDEX block, %d chunks for %d frames (fpos=%"PRId64").\n",
- priv->idx_size,avih.dwTotalFrames, (int64_t)stream_tell(demuxer->stream));
- priv->idx=malloc(priv->idx_size<<4);
-// printf("\nindex to %p !!!!! (priv=%p)\n",priv->idx,priv);
- read = stream_read(demuxer->stream,(char*)priv->idx,priv->idx_size<<4);
- priv->idx_size = FFMAX(read, 0) >> 4;
- for (i = 0; i < priv->idx_size; i++) { // swap index to machine endian
- AVIINDEXENTRY *entry=(AVIINDEXENTRY*)priv->idx + i;
- le2me_AVIINDEXENTRY(entry);
- /*
- * We (ab)use the upper word for bits 32-47 of the offset, so
- * we'll clear them here.
- * FIXME: AFAIK no codec uses them, but if one does it will break
- */
- entry->dwFlags&=0xffff;
- }
- chunksize-=priv->idx_size<<4;
- if( mp_msg_test(MSGT_HEADER,MSGL_DBG2) ) print_index(priv->idx,priv->idx_size,MSGL_DBG2);
- }
- break;
- /* added May 2002 */
- case mmioFOURCC('R','I','F','F'): {
- char riff_type[4];
-
- mp_tmsg(MSGT_HEADER, MSGL_V, "Additional RIFF header...\n");
- stream_read(demuxer->stream, riff_type, sizeof riff_type);
- if (strncmp(riff_type, "AVIX", sizeof riff_type))
- mp_tmsg(MSGT_HEADER, MSGL_WARN, "** Warning: this is no extended AVI header..\n");
- else {
- /*
- * We got an extended AVI header, so we need to switch to
- * ODML to get seeking to work, provided we got indx chunks
- * in the header (suidx_size > 0).
- */
- if (priv->suidx_size > 0)
- priv->isodml = 1;
- }
- chunksize = 0;
- list_end = 0; /* a new list will follow */
- break; }
- case ckidAVIPADDING:
- stream_skip(demuxer->stream, chunksize);
- chunksize = 0;
- break;
- }
- if(hdr){
- mp_msg(MSGT_HEADER,MSGL_V,"hdr=%s size=%u\n",hdr,size2);
- if(size2==3)
- chunksize=1; // empty
- else {
- char buf[256];
- int len=(size2<250)?size2:250;
- stream_read(demuxer->stream,buf,len);
- chunksize-=len;
- buf[len]=0;
- mp_msg(MSGT_HEADER,MSGL_V,"%-10s: %s\n",hdr,buf);
- demux_info_add(demuxer, hdr, buf);
- }
- }
- mp_msg(MSGT_HEADER,MSGL_DBG2,"list_end=0x%"PRIX64" pos=0x%"PRIX64" chunksize=0x%"PRIX64" next=0x%"PRIX64"\n",
- (int64_t)list_end, (int64_t)stream_tell(demuxer->stream),
- (int64_t)chunksize, (int64_t)chunksize+(int64_t)stream_tell(demuxer->stream));
- if(list_end>0 &&
- chunksize+stream_tell(demuxer->stream) == list_end) list_end=0;
- if(list_end>0 && chunksize+stream_tell(demuxer->stream)>list_end){
- mp_tmsg(MSGT_HEADER,MSGL_V,"Broken chunk? chunksize=%d (id=%.4s)\n",chunksize,(char *) &id);
- stream_seek(demuxer->stream,list_end);
- list_end=0;
- } else
- if(chunksize>0) stream_skip(demuxer->stream,chunksize); else
- if((int)chunksize<0) mp_msg(MSGT_HEADER,MSGL_WARN,"chunksize=%u (id=%.4s)\n",chunksize,(char *) &id);
-
-}
-
-if (priv->suidx_size > 0 && priv->idx_size == 0) {
- /*
- * No NEWAVIINDEX, but we got an OpenDML index.
- */
- priv->isodml = 1;
-}
-
-if (priv->isodml && (index_mode==-1 || index_mode==0 || index_mode==1)) {
- int i, j, k;
-
- avisuperindex_chunk *cx;
- AVIINDEXENTRY *idx;
-
-
- if (priv->idx_size) free(priv->idx);
- priv->idx_size = 0;
- priv->idx_offset = 0;
- priv->idx = NULL;
-
- mp_tmsg(MSGT_HEADER, MSGL_INFO, "AVI: ODML: Building ODML index (%d superindexchunks).\n", priv->suidx_size);
-
- // read the standard indices
- for (cx = &priv->suidx[0], i=0; i<priv->suidx_size; cx++, i++) {
- for (j=0; j<cx->nEntriesInUse; j++) {
- int ret1, ret2;
- memset(&cx->stdidx[j], 0, 32);
- ret1 = stream_seek(demuxer->stream, (int64_t)cx->aIndex[j].qwOffset);
- ret2 = stream_read(demuxer->stream, (char *)&cx->stdidx[j], 32);
- if (ret1 != 1 || ret2 != 32 || cx->stdidx[j].nEntriesInUse==0) {
- // this is a broken file (probably incomplete) let the standard
- // gen_index routine handle this
- priv->isodml = 0;
- priv->idx_size = 0;
- mp_tmsg(MSGT_HEADER, MSGL_WARN, "AVI: ODML: Broken (incomplete?) file detected. Will use traditional index.\n");
- goto freeout;
- }
-
- le2me_AVISTDIDXCHUNK(&cx->stdidx[j]);
- print_avistdindex_chunk(&cx->stdidx[j],MSGL_V);
- priv->idx_size += cx->stdidx[j].nEntriesInUse;
- cx->stdidx[j].aIndex = malloc(cx->stdidx[j].nEntriesInUse*sizeof(avistdindex_entry));
- stream_read(demuxer->stream, (char *)cx->stdidx[j].aIndex,
- cx->stdidx[j].nEntriesInUse*sizeof(avistdindex_entry));
- for (k=0;k<cx->stdidx[j].nEntriesInUse; k++)
- le2me_AVISTDIDXENTRY(&cx->stdidx[j].aIndex[k]);
-
- cx->stdidx[j].dwReserved3 = 0;
-
- }
- }
-
- /*
- * We convert the index by translating all entries into AVIINDEXENTRYs
- * and sorting them by offset. The result should be the same index
- * we would get with -forceidx.
- */
-
- idx = priv->idx = malloc(priv->idx_size * sizeof (AVIINDEXENTRY));
-
- for (cx = priv->suidx; cx != &priv->suidx[priv->suidx_size]; cx++) {
- avistdindex_chunk *sic;
- for (sic = cx->stdidx; sic != &cx->stdidx[cx->nEntriesInUse]; sic++) {
- avistdindex_entry *sie;
- for (sie = sic->aIndex; sie != &sic->aIndex[sic->nEntriesInUse]; sie++) {
- uint64_t off = sic->qwBaseOffset + sie->dwOffset - 8;
- memcpy(&idx->ckid, sic->dwChunkId, 4);
- idx->dwChunkOffset = off;
- idx->dwFlags = (off >> 32) << 16;
- idx->dwChunkLength = sie->dwSize & 0x7fffffff;
- idx->dwFlags |= (sie->dwSize&0x80000000)?0x0:AVIIF_KEYFRAME; // bit 31 denotes !keyframe
- idx++;
- }
- }
- }
- qsort(priv->idx, priv->idx_size, sizeof(AVIINDEXENTRY), avi_idx_cmp);
-
- /*
- Hack to work around a "wrong" index in some divx odml files
- (processor_burning.avi as an example)
- They have ##dc on non keyframes but the ix00 tells us they are ##db.
- Read the fcc of a non-keyframe vid frame and check it.
- */
-
- {
- uint32_t id;
- uint32_t db = 0;
-
- // find out the video stream id. I have seen files with 01db.
- for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){
- unsigned char res[2];
- if (odml_get_vstream_id(idx->ckid, res)) {
- db = mmioFOURCC(res[0], res[1], 'd', 'b');
- break;
- }
- }
-
- // find first non keyframe
- for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){
- if (!(idx->dwFlags & AVIIF_KEYFRAME) && idx->ckid == db) break;
- }
- if (i<priv->idx_size && db) {
- stream_seek(demuxer->stream, AVI_IDX_OFFSET(idx));
- id = stream_read_dword_le(demuxer->stream);
- if (id && id != db) // index fcc and real fcc differ? fix it.
- for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){
- if (!(idx->dwFlags & AVIIF_KEYFRAME) && idx->ckid == db)
- idx->ckid = id;
- }
- }
- }
-
- if ( mp_msg_test(MSGT_HEADER,MSGL_DBG2) ) print_index(priv->idx, priv->idx_size,MSGL_DBG2);
-
- demuxer->movi_end=demuxer->stream->end_pos;
-
-freeout:
-
- // free unneeded stuff
- cx = &priv->suidx[0];
- do {
- for (j=0;j<cx->nEntriesInUse;j++)
- if (cx->stdidx[j].nEntriesInUse) free(cx->stdidx[j].aIndex);
- free(cx->stdidx);
-
- } while (cx++ != &priv->suidx[priv->suidx_size-1]);
- free(priv->suidx);
-
-}
-
-if(index_mode>=2 || (priv->idx_size==0 && index_mode==1)){
- int idx_pos = 0;
- // build index for file:
- stream_seek(demuxer->stream,demuxer->movi_start);
-
- priv->idx_size=0;
- priv->idx=NULL;
-
- while(1){
- int id;
- unsigned len;
- int64_t skip;
- AVIINDEXENTRY* idx;
- unsigned int c;
- demuxer->filepos=stream_tell(demuxer->stream);
- if(demuxer->filepos>=demuxer->movi_end && demuxer->movi_start<demuxer->movi_end) break;
- id=stream_read_dword_le(demuxer->stream);
- len=stream_read_dword_le(demuxer->stream);
- if(id==mmioFOURCC('L','I','S','T') || id==mmioFOURCC('R', 'I', 'F', 'F')){
- id=stream_read_dword_le(demuxer->stream); // list or RIFF type
- continue;
- }
- if(stream_eof(demuxer->stream)) break;
- if(!id || avi_stream_id(id)==100) goto skip_chunk; // bad ID (or padding?)
-
- if(idx_pos>=priv->idx_size){
-// priv->idx_size+=32;
- priv->idx_size+=1024; // +16kB
- priv->idx=realloc(priv->idx,priv->idx_size*sizeof(AVIINDEXENTRY));
- if(!priv->idx){idx_pos=0; break;} // error!
- }
- idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos++];
- idx->ckid=id;
- idx->dwFlags=AVIIF_KEYFRAME; // FIXME
- idx->dwFlags|=(demuxer->filepos>>16)&0xffff0000U;
- idx->dwChunkOffset=(unsigned long)demuxer->filepos;
- idx->dwChunkLength=len;
-
- c=stream_read_dword(demuxer->stream);
-
- if(!len) idx->dwFlags&=~AVIIF_KEYFRAME;
-
- // Fix keyframes for DivX files:
- if(idxfix_divx)
- if(avi_stream_id(id)==idxfix_videostream){
- switch(idxfix_divx){
- case 3: c=stream_read_dword(demuxer->stream)<<5; //skip 32+5 bits for m$mpeg4v1
- case 1: if(c&0x40000000) idx->dwFlags&=~AVIIF_KEYFRAME;break; // divx 3
- case 2: if(c==0x1B6) idx->dwFlags&=~AVIIF_KEYFRAME;break; // divx 4
- }
- }
-
- // update status line:
- { static int64_t lastpos;
- int64_t pos;
- int64_t len=demuxer->movi_end-demuxer->movi_start;
- if(len){
- pos=100*(demuxer->filepos-demuxer->movi_start)/len; // %
- } else {
- pos=(demuxer->filepos-demuxer->movi_start)>>20; // MB
- }
- if(pos!=lastpos){
- lastpos=pos;
- mp_tmsg(MSGT_HEADER,MSGL_STATUS, "Generating Index: %3lu %s \r",
- (unsigned long)pos, len?"%":"MB");
- }
- }
- mp_dbg(MSGT_HEADER,MSGL_DBG2,"%08X %08X %.4s %08X %X\n",(unsigned int)demuxer->filepos,id,(char *) &id,(int)c,(unsigned int) idx->dwFlags);
-#if 0
- { unsigned char tmp[64];
- int i;
- stream_read(demuxer->stream,tmp,64);
- printf("%.4s",&id);
- for(i=0;i<64;i++) printf(" %02X",tmp[i]);
- printf("\n");
- }
-#endif
-skip_chunk:
- skip=(len+1)&(~1UL); // total bytes in this chunk
- stream_seek(demuxer->stream,8+demuxer->filepos+skip);
- }
- priv->idx_size=idx_pos;
- mp_tmsg(MSGT_HEADER,MSGL_INFO,"AVI: Generated index table for %d chunks!\n",priv->idx_size);
- if( mp_msg_test(MSGT_HEADER,MSGL_DBG2) ) print_index(priv->idx,priv->idx_size,MSGL_DBG2);
-
-}
-}
diff --git a/demux/aviheader.h b/demux/aviheader.h
deleted file mode 100644
index 0d721908d3..0000000000
--- a/demux/aviheader.h
+++ /dev/null
@@ -1,382 +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_AVIHEADER_H
-#define MPLAYER_AVIHEADER_H
-
-#include <sys/types.h>
-#include <stdint.h>
-#include "config.h"
-#include "libavutil/common.h"
-#include "compat/mpbswap.h"
-
-#ifndef mmioFOURCC
-#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
- ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
- ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
-#endif
-
-/* Macro to make a TWOCC out of two characters */
-#ifndef aviTWOCC
-#define aviTWOCC(ch0, ch1) ((uint16_t)(uint8_t)(ch0) | ((uint16_t)(uint8_t)(ch1) << 8))
-#endif
-
-//typedef uint16_t TWOCC;
-//typedef uint32_t FOURCC;
-
-/* form types, list types, and chunk types */
-#define formtypeAVI mmioFOURCC('A', 'V', 'I', ' ')
-#define listtypeAVIHEADER mmioFOURCC('h', 'd', 'r', 'l')
-#define ckidAVIMAINHDR mmioFOURCC('a', 'v', 'i', 'h')
-#define listtypeSTREAMHEADER mmioFOURCC('s', 't', 'r', 'l')
-#define ckidSTREAMHEADER mmioFOURCC('s', 't', 'r', 'h')
-#define ckidSTREAMFORMAT mmioFOURCC('s', 't', 'r', 'f')
-#define ckidSTREAMHANDLERDATA mmioFOURCC('s', 't', 'r', 'd')
-#define ckidSTREAMNAME mmioFOURCC('s', 't', 'r', 'n')
-
-#define listtypeAVIMOVIE mmioFOURCC('m', 'o', 'v', 'i')
-#define listtypeAVIRECORD mmioFOURCC('r', 'e', 'c', ' ')
-
-#define ckidAVINEWINDEX mmioFOURCC('i', 'd', 'x', '1')
-
-/*
-** Stream types for the <fccType> field of the stream header.
-*/
-#define streamtypeVIDEO mmioFOURCC('v', 'i', 'd', 's')
-#define streamtypeAUDIO mmioFOURCC('a', 'u', 'd', 's')
-#define streamtypeMIDI mmioFOURCC('m', 'i', 'd', 's')
-#define streamtypeTEXT mmioFOURCC('t', 'x', 't', 's')
-
-/* Basic chunk types */
-#define cktypeDIBbits aviTWOCC('d', 'b')
-#define cktypeDIBcompressed aviTWOCC('d', 'c')
-#define cktypePALchange aviTWOCC('p', 'c')
-#define cktypeWAVEbytes aviTWOCC('w', 'b')
-
-/* Chunk id to use for extra chunks for padding. */
-#define ckidAVIPADDING mmioFOURCC('J', 'U', 'N', 'K')
-
-/* flags for use in <dwFlags> in AVIFileHdr */
-#define AVIF_HASINDEX 0x00000010 // Index at end of file?
-#define AVIF_MUSTUSEINDEX 0x00000020
-#define AVIF_ISINTERLEAVED 0x00000100
-#define AVIF_TRUSTCKTYPE 0x00000800 // Use CKType to find key frames?
-#define AVIF_WASCAPTUREFILE 0x00010000
-#define AVIF_COPYRIGHTED 0x00020000
-
-typedef struct
-{
- uint32_t dwMicroSecPerFrame; // frame display rate (or 0L)
- uint32_t dwMaxBytesPerSec; // max. transfer rate
- uint32_t dwPaddingGranularity; // pad to multiples of this
- // size; normally 2K.
- uint32_t dwFlags; // the ever-present flags
- uint32_t dwTotalFrames; // # frames in file
- uint32_t dwInitialFrames;
- uint32_t dwStreams;
- uint32_t dwSuggestedBufferSize;
-
- uint32_t dwWidth;
- uint32_t dwHeight;
-
- uint32_t dwReserved[4];
-} MainAVIHeader;
-
-typedef struct rectangle_t {
- short left;
- short top;
- short right;
- short bottom;
-} rectangle_t;
-
-typedef struct {
- uint32_t fccType;
- uint32_t fccHandler;
- uint32_t dwFlags; /* Contains AVITF_* flags */
- uint16_t wPriority;
- uint16_t wLanguage;
- uint32_t dwInitialFrames;
- uint32_t dwScale;
- uint32_t dwRate; /* dwRate / dwScale == samples/second */
- uint32_t dwStart;
- uint32_t dwLength; /* In units above... */
- uint32_t dwSuggestedBufferSize;
- uint32_t dwQuality;
- uint32_t dwSampleSize;
- rectangle_t rcFrame;
-} AVIStreamHeader;
-
-/* Flags for index */
-#define AVIIF_LIST 0x00000001L // chunk is a 'LIST'
-#define AVIIF_KEYFRAME 0x00000010L // this frame is a key frame.
-
-#define AVIIF_NOTIME 0x00000100L // this frame doesn't take any time
-#define AVIIF_COMPUSE 0x0FFF0000L // these bits are for compressor use
-
-#ifndef FOURCC_RIFF
-#define FOURCC_RIFF mmioFOURCC('R', 'I', 'F', 'F')
-#define FOURCC_LIST mmioFOURCC('L', 'I', 'S', 'T')
-#endif
-
-typedef struct
-{
- uint32_t ckid;
- uint32_t dwFlags;
- uint32_t dwChunkOffset; // Position of chunk
- uint32_t dwChunkLength; // Length of chunk
-} AVIINDEXENTRY;
-
-
-typedef struct avisuperindex_entry {
- uint64_t qwOffset; // absolute file offset
- uint32_t dwSize; // size of index chunk at this offset
- uint32_t dwDuration; // time span in stream ticks
-} avisuperindex_entry;
-
-typedef struct avistdindex_entry {
- uint32_t dwOffset; // qwBaseOffset + this is absolute file offset
- uint32_t dwSize; // bit 31 is set if this is NOT a keyframe
-} avistdindex_entry;
-
-// Standard index
-typedef struct __attribute__((packed)) avistdindex_chunk {
- char fcc[4]; // ix##
- uint32_t dwSize; // size of this chunk
- uint16_t wLongsPerEntry; // must be sizeof(aIndex[0])/sizeof(DWORD)
- uint8_t bIndexSubType; // must be 0
- uint8_t bIndexType; // must be AVI_INDEX_OF_CHUNKS
- uint32_t nEntriesInUse; // first unused entry
- char dwChunkId[4]; // '##dc' or '##db' or '##wb' etc..
- uint64_t qwBaseOffset; // all dwOffsets in aIndex array are relative to this
- uint32_t dwReserved3; // must be 0
- avistdindex_entry *aIndex; // the actual frames
-} avistdindex_chunk;
-
-
-// Base Index Form 'indx'
-typedef struct avisuperindex_chunk {
- char fcc[4];
- uint32_t dwSize; // size of this chunk
- uint16_t wLongsPerEntry; // size of each entry in aIndex array (must be 4*4 for us)
- uint8_t bIndexSubType; // future use. must be 0
- uint8_t bIndexType; // one of AVI_INDEX_* codes
- uint32_t nEntriesInUse; // index of first unused member in aIndex array
- char dwChunkId[4]; // fcc of what is indexed
- uint32_t dwReserved[3]; // meaning differs for each index type/subtype.
- // 0 if unused
- avisuperindex_entry *aIndex; // position of ix## chunks
- avistdindex_chunk *stdidx; // the actual std indices
-} avisuperindex_chunk;
-
-typedef struct {
- uint32_t CompressedBMHeight;
- uint32_t CompressedBMWidth;
- uint32_t ValidBMHeight;
- uint32_t ValidBMWidth;
- uint32_t ValidBMXOffset;
- uint32_t ValidBMYOffset;
- uint32_t VideoXOffsetInT;
- uint32_t VideoYValidStartLine;
-} VIDEO_FIELD_DESC;
-
-typedef struct {
- uint32_t VideoFormatToken;
- uint32_t VideoStandard;
- uint32_t dwVerticalRefreshRate;
- uint32_t dwHTotalInT;
- uint32_t dwVTotalInLines;
- uint32_t dwFrameAspectRatio;
- uint32_t dwFrameWidthInPixels;
- uint32_t dwFrameHeightInLines;
- uint32_t nbFieldPerFrame;
- VIDEO_FIELD_DESC FieldInfo[2];
-} VideoPropHeader;
-
-typedef enum {
- FORMAT_UNKNOWN,
- FORMAT_PAL_SQUARE,
- FORMAT_PAL_CCIR_601,
- FORMAT_NTSC_SQUARE,
- FORMAT_NTSC_CCIR_601,
-} VIDEO_FORMAT;
-
-typedef enum {
- STANDARD_UNKNOWN,
- STANDARD_PAL,
- STANDARD_NTSC,
- STANDARD_SECAM
-} VIDEO_STANDARD;
-
-#define MAKE_AVI_ASPECT(a, b) (((a)<<16)|(b))
-#define GET_AVI_ASPECT(a) ((float)((a)>>16)/(float)((a)&0xffff))
-
-/*
- * Some macros to swap little endian structures read from an AVI file
- * into machine endian format
- */
-#if BYTE_ORDER == BIG_ENDIAN
-#define le2me_MainAVIHeader(h) { \
- (h)->dwMicroSecPerFrame = le2me_32((h)->dwMicroSecPerFrame); \
- (h)->dwMaxBytesPerSec = le2me_32((h)->dwMaxBytesPerSec); \
- (h)->dwPaddingGranularity = le2me_32((h)->dwPaddingGranularity); \
- (h)->dwFlags = le2me_32((h)->dwFlags); \
- (h)->dwTotalFrames = le2me_32((h)->dwTotalFrames); \
- (h)->dwInitialFrames = le2me_32((h)->dwInitialFrames); \
- (h)->dwStreams = le2me_32((h)->dwStreams); \
- (h)->dwSuggestedBufferSize = le2me_32((h)->dwSuggestedBufferSize); \
- (h)->dwWidth = le2me_32((h)->dwWidth); \
- (h)->dwHeight = le2me_32((h)->dwHeight); \
-}
-
-#define le2me_AVIStreamHeader(h) { \
- (h)->fccType = le2me_32((h)->fccType); \
- (h)->fccHandler = le2me_32((h)->fccHandler); \
- (h)->dwFlags = le2me_32((h)->dwFlags); \
- (h)->wPriority = le2me_16((h)->wPriority); \
- (h)->wLanguage = le2me_16((h)->wLanguage); \
- (h)->dwInitialFrames = le2me_32((h)->dwInitialFrames); \
- (h)->dwScale = le2me_32((h)->dwScale); \
- (h)->dwRate = le2me_32((h)->dwRate); \
- (h)->dwStart = le2me_32((h)->dwStart); \
- (h)->dwLength = le2me_32((h)->dwLength); \
- (h)->dwSuggestedBufferSize = le2me_32((h)->dwSuggestedBufferSize); \
- (h)->dwQuality = le2me_32((h)->dwQuality); \
- (h)->dwSampleSize = le2me_32((h)->dwSampleSize); \
- le2me_RECT(&(h)->rcFrame); \
-}
-#define le2me_RECT(h) { \
- (h)->left = le2me_16((h)->left); \
- (h)->top = le2me_16((h)->top); \
- (h)->right = le2me_16((h)->right); \
- (h)->bottom = le2me_16((h)->bottom); \
-}
-#define le2me_BITMAPINFOHEADER(h) { \
- (h)->biSize = le2me_32((h)->biSize); \
- (h)->biWidth = le2me_32((h)->biWidth); \
- (h)->biHeight = le2me_32((h)->biHeight); \
- (h)->biPlanes = le2me_16((h)->biPlanes); \
- (h)->biBitCount = le2me_16((h)->biBitCount); \
- (h)->biCompression = le2me_32((h)->biCompression); \
- (h)->biSizeImage = le2me_32((h)->biSizeImage); \
- (h)->biXPelsPerMeter = le2me_32((h)->biXPelsPerMeter); \
- (h)->biYPelsPerMeter = le2me_32((h)->biYPelsPerMeter); \
- (h)->biClrUsed = le2me_32((h)->biClrUsed); \
- (h)->biClrImportant = le2me_32((h)->biClrImportant); \
-}
-#define le2me_WAVEFORMATEX(h) { \
- (h)->wFormatTag = le2me_16((h)->wFormatTag); \
- (h)->nChannels = le2me_16((h)->nChannels); \
- (h)->nSamplesPerSec = le2me_32((h)->nSamplesPerSec); \
- (h)->nAvgBytesPerSec = le2me_32((h)->nAvgBytesPerSec); \
- (h)->nBlockAlign = le2me_16((h)->nBlockAlign); \
- (h)->wBitsPerSample = le2me_16((h)->wBitsPerSample); \
- (h)->cbSize = le2me_16((h)->cbSize); \
-}
-#define le2me_AVIINDEXENTRY(h) { \
- (h)->ckid = le2me_32((h)->ckid); \
- (h)->dwFlags = le2me_32((h)->dwFlags); \
- (h)->dwChunkOffset = le2me_32((h)->dwChunkOffset); \
- (h)->dwChunkLength = le2me_32((h)->dwChunkLength); \
-}
-#define le2me_AVISTDIDXCHUNK(h) {\
- char c; \
- c = (h)->fcc[0]; (h)->fcc[0] = (h)->fcc[3]; (h)->fcc[3] = c; \
- c = (h)->fcc[1]; (h)->fcc[1] = (h)->fcc[2]; (h)->fcc[2] = c; \
- (h)->dwSize = le2me_32((h)->dwSize); \
- (h)->wLongsPerEntry = le2me_16((h)->wLongsPerEntry); \
- (h)->nEntriesInUse = le2me_32((h)->nEntriesInUse); \
- c = (h)->dwChunkId[0]; (h)->dwChunkId[0] = (h)->dwChunkId[3]; (h)->dwChunkId[3] = c; \
- c = (h)->dwChunkId[1]; (h)->dwChunkId[1] = (h)->dwChunkId[2]; (h)->dwChunkId[2] = c; \
- (h)->qwBaseOffset = le2me_64((h)->qwBaseOffset); \
- (h)->dwReserved3 = le2me_32((h)->dwReserved3); \
-}
-#define le2me_AVISTDIDXENTRY(h) {\
- (h)->dwOffset = le2me_32((h)->dwOffset); \
- (h)->dwSize = le2me_32((h)->dwSize); \
-}
-#define le2me_VideoPropHeader(h) { \
- (h)->VideoFormatToken = le2me_32((h)->VideoFormatToken); \
- (h)->VideoStandard = le2me_32((h)->VideoStandard); \
- (h)->dwVerticalRefreshRate = le2me_32((h)->dwVerticalRefreshRate); \
- (h)->dwHTotalInT = le2me_32((h)->dwHTotalInT); \
- (h)->dwVTotalInLines = le2me_32((h)->dwVTotalInLines); \
- (h)->dwFrameAspectRatio = le2me_32((h)->dwFrameAspectRatio); \
- (h)->dwFrameWidthInPixels = le2me_32((h)->dwFrameWidthInPixels); \
- (h)->dwFrameHeightInLines = le2me_32((h)->dwFrameHeightInLines); \
- (h)->nbFieldPerFrame = le2me_32((h)->nbFieldPerFrame); \
-}
-#define le2me_VIDEO_FIELD_DESC(h) { \
- (h)->CompressedBMHeight = le2me_32((h)->CompressedBMHeight); \
- (h)->CompressedBMWidth = le2me_32((h)->CompressedBMWidth); \
- (h)->ValidBMHeight = le2me_32((h)->ValidBMHeight); \
- (h)->ValidBMWidth = le2me_32((h)->ValidBMWidth); \
- (h)->ValidBMXOffset = le2me_32((h)->ValidBMXOffset); \
- (h)->ValidBMYOffset = le2me_32((h)->ValidBMYOffset); \
- (h)->VideoXOffsetInT = le2me_32((h)->VideoXOffsetInT); \
- (h)->VideoYValidStartLine = le2me_32((h)->VideoYValidStartLine); \
-}
-
-#else
-#define le2me_MainAVIHeader(h) /**/
-#define le2me_AVIStreamHeader(h) /**/
-#define le2me_RECT(h) /**/
-#define le2me_BITMAPINFOHEADER(h) /**/
-#define le2me_WAVEFORMATEX(h) /**/
-#define le2me_AVIINDEXENTRY(h) /**/
-#define le2me_AVISTDIDXCHUNK(h) /**/
-#define le2me_AVISTDIDXENTRY(h) /**/
-#define le2me_VideoPropHeader(h) /**/
-#define le2me_VIDEO_FIELD_DESC(h) /**/
-#endif
-
-typedef struct {
- // index stuff:
- void* idx;
- int idx_size;
- int64_t idx_pos;
- int64_t idx_pos_a;
- int64_t idx_pos_v;
- int64_t idx_offset; // ennyit kell hozzaadni az index offset ertekekhez
- // bps-based PTS stuff:
- int video_pack_no;
- int audio_block_size;
- int64_t audio_block_no;
- // interleaved PTS stuff:
- int skip_video_frames;
- int audio_streams;
- float avi_audio_pts;
- float avi_video_pts;
- float pts_correction;
- unsigned int pts_corr_bytes;
- unsigned char pts_corrected;
- unsigned char pts_has_video;
- unsigned int numberofframes;
- avisuperindex_chunk *suidx;
- int suidx_size;
- int isodml;
- int warned_unaligned;
-} avi_priv_t;
-
-#define AVI_PRIV ((avi_priv_t*)(demuxer->priv))
-
-#define AVI_IDX_OFFSET(x) ((((uint64_t)(x)->dwFlags&0xffff0000)<<16)+(x)->dwChunkOffset)
-
-struct demuxer;
-void read_avi_header(struct demuxer *demuxer, int index_mode);
-
-#endif /* MPLAYER_AVIHEADER_H */
diff --git a/demux/aviprint.c b/demux/aviprint.c
deleted file mode 100644
index 5d285c2104..0000000000
--- a/demux/aviprint.c
+++ /dev/null
@@ -1,197 +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 <unistd.h>
-#include <inttypes.h>
-
-#include "config.h"
-
-// for avi_stream_id():
-#include "stream/stream.h"
-#include "demux.h"
-
-#include "aviheader.h"
-#include "ms_hdr.h"
-#include "aviprint.h"
-
-//#include "codec-cfg.h"
-//#include "stheader.h"
-
-void print_avih_flags(MainAVIHeader *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "MainAVIHeader.dwFlags: (%"PRId32")%s%s%s%s%s%s\n",h->dwFlags,
- (h->dwFlags&AVIF_HASINDEX)?" HAS_INDEX":"",
- (h->dwFlags&AVIF_MUSTUSEINDEX)?" MUST_USE_INDEX":"",
- (h->dwFlags&AVIF_ISINTERLEAVED)?" IS_INTERLEAVED":"",
- (h->dwFlags&AVIF_TRUSTCKTYPE)?" TRUST_CKTYPE":"",
- (h->dwFlags&AVIF_WASCAPTUREFILE)?" WAS_CAPTUREFILE":"",
- (h->dwFlags&AVIF_COPYRIGHTED)?" COPYRIGHTED":""
- );
-}
-
-void print_avih(MainAVIHeader *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "======= AVI Header =======\n");
- mp_msg(MSGT_HEADER, verbose_level, "us/frame: %"PRId32" (fps=%5.3f)\n",h->dwMicroSecPerFrame,1000000.0f/(float)h->dwMicroSecPerFrame);
- mp_msg(MSGT_HEADER, verbose_level, "max bytes/sec: %"PRId32"\n",h->dwMaxBytesPerSec);
- mp_msg(MSGT_HEADER, verbose_level, "padding: %"PRId32"\n",h->dwPaddingGranularity);
- print_avih_flags(h, verbose_level);
- mp_msg(MSGT_HEADER, verbose_level, "frames total: %"PRId32" initial: %"PRId32"\n",h->dwTotalFrames,h->dwInitialFrames);
- mp_msg(MSGT_HEADER, verbose_level, "streams: %"PRId32"\n",h->dwStreams);
- mp_msg(MSGT_HEADER, verbose_level, "Suggested BufferSize: %"PRId32"\n",h->dwSuggestedBufferSize);
- mp_msg(MSGT_HEADER, verbose_level, "Size: %"PRId32" x %"PRId32"\n",h->dwWidth,h->dwHeight);
- mp_msg(MSGT_HEADER, verbose_level, "==========================\n");
-}
-
-void print_strh(AVIStreamHeader *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "====== STREAM Header =====\n");
- mp_msg(MSGT_HEADER, verbose_level, "Type: %.4s FCC: %.4s (%X)\n",(char *)&h->fccType,(char *)&h->fccHandler,(unsigned int)h->fccHandler);
- mp_msg(MSGT_HEADER, verbose_level, "Flags: %"PRId32"\n",h->dwFlags);
- mp_msg(MSGT_HEADER, verbose_level, "Priority: %d Language: %d\n",h->wPriority,h->wLanguage);
- mp_msg(MSGT_HEADER, verbose_level, "InitialFrames: %"PRId32"\n",h->dwInitialFrames);
- mp_msg(MSGT_HEADER, verbose_level, "Rate: %"PRId32"/%"PRId32" = %5.3f\n",h->dwRate,h->dwScale,(float)h->dwRate/(float)h->dwScale);
- mp_msg(MSGT_HEADER, verbose_level, "Start: %"PRId32" Len: %"PRId32"\n",h->dwStart,h->dwLength);
- mp_msg(MSGT_HEADER, verbose_level, "Suggested BufferSize: %"PRId32"\n",h->dwSuggestedBufferSize);
- mp_msg(MSGT_HEADER, verbose_level, "Quality %"PRId32"\n",h->dwQuality);
- mp_msg(MSGT_HEADER, verbose_level, "Sample size: %"PRId32"\n",h->dwSampleSize);
- mp_msg(MSGT_HEADER, verbose_level, "==========================\n");
-}
-
-void print_wave_header(WAVEFORMATEX *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "======= WAVE Format =======\n");
- mp_msg(MSGT_HEADER, verbose_level, "Format Tag: %d (0x%X)\n",h->wFormatTag,h->wFormatTag);
- mp_msg(MSGT_HEADER, verbose_level, "Channels: %d\n",h->nChannels);
- mp_msg(MSGT_HEADER, verbose_level, "Samplerate: %"PRId32"\n",h->nSamplesPerSec);
- mp_msg(MSGT_HEADER, verbose_level, "avg byte/sec: %"PRId32"\n",h->nAvgBytesPerSec);
- mp_msg(MSGT_HEADER, verbose_level, "Block align: %d\n",h->nBlockAlign);
- mp_msg(MSGT_HEADER, verbose_level, "bits/sample: %d\n",h->wBitsPerSample);
- mp_msg(MSGT_HEADER, verbose_level, "cbSize: %d\n",h->cbSize);
- if(h->wFormatTag==0x55 && h->cbSize>=12){
- MPEGLAYER3WAVEFORMAT* h2=(MPEGLAYER3WAVEFORMAT *)h;
- mp_msg(MSGT_HEADER, verbose_level, "mp3.wID=%d\n",h2->wID);
- mp_msg(MSGT_HEADER, verbose_level, "mp3.fdwFlags=0x%"PRIX32"\n",h2->fdwFlags);
- mp_msg(MSGT_HEADER, verbose_level, "mp3.nBlockSize=%d\n",h2->nBlockSize);
- mp_msg(MSGT_HEADER, verbose_level, "mp3.nFramesPerBlock=%d\n",h2->nFramesPerBlock);
- mp_msg(MSGT_HEADER, verbose_level, "mp3.nCodecDelay=%d\n",h2->nCodecDelay);
- }
- else if (h->wFormatTag == 0xfffe && h->cbSize >= 22) {
- WAVEFORMATEXTENSIBLE *h2 = (WAVEFORMATEXTENSIBLE *)h;
- mp_msg(MSGT_HEADER, verbose_level, "ex.wValidBitsPerSample=%d\n", h2->wValidBitsPerSample);
- mp_msg(MSGT_HEADER, verbose_level, "ex.dwChannelMask=0x%X\n", h2->dwChannelMask);
- mp_msg(MSGT_HEADER, verbose_level, "ex.SubFormat=%d (0x%X)\n", h2->SubFormat, h2->SubFormat);
- }
- else if (h->cbSize > 0)
- {
- int i;
- uint8_t* p = (uint8_t*)(h + 1);
- mp_msg(MSGT_HEADER, verbose_level, "Unknown extra header dump: ");
- for (i = 0; i < h->cbSize; i++)
- mp_msg(MSGT_HEADER, verbose_level, "[%x] ", p[i]);
- mp_msg(MSGT_HEADER, verbose_level, "\n");
- }
- mp_msg(MSGT_HEADER, verbose_level, "==========================================================================\n");
-}
-
-
-void print_video_header(BITMAPINFOHEADER *h, int verbose_level){
- mp_msg(MSGT_HEADER, verbose_level, "======= VIDEO Format ======\n");
- mp_msg(MSGT_HEADER, verbose_level, " biSize %d\n", h->biSize);
- mp_msg(MSGT_HEADER, verbose_level, " biWidth %d\n", h->biWidth);
- mp_msg(MSGT_HEADER, verbose_level, " biHeight %d\n", h->biHeight);
- mp_msg(MSGT_HEADER, verbose_level, " biPlanes %d\n", h->biPlanes);
- mp_msg(MSGT_HEADER, verbose_level, " biBitCount %d\n", h->biBitCount);
- mp_msg(MSGT_HEADER, verbose_level, " biCompression %d='%.4s'\n", h->biCompression, (char *)&h->biCompression);
- mp_msg(MSGT_HEADER, verbose_level, " biSizeImage %d\n", h->biSizeImage);
- if (h->biSize > sizeof(*h))
- {
- int i;
- uint8_t* p = (uint8_t*)(h + 1);
- mp_msg(MSGT_HEADER, verbose_level, "Unknown extra header dump: ");
- for (i = 0; i < h->biSize-sizeof(*h); i++)
- mp_msg(MSGT_HEADER, verbose_level, "[%x] ", *(p+i));
- mp_msg(MSGT_HEADER, verbose_level, "\n");
- }
- mp_msg(MSGT_HEADER, verbose_level, "===========================\n");
-}
-
-void print_vprp(VideoPropHeader *vprp, int verbose_level){
- int i;
- mp_msg(MSGT_HEADER, verbose_level, "======= Video Properties Header =======\n");
- mp_msg(MSGT_HEADER, verbose_level, "Format: %d VideoStandard: %d\n",
- vprp->VideoFormatToken,vprp->VideoStandard);
- mp_msg(MSGT_HEADER, verbose_level, "VRefresh: %d HTotal: %d VTotal: %d\n",
- vprp->dwVerticalRefreshRate, vprp->dwHTotalInT, vprp->dwVTotalInLines);
- mp_msg(MSGT_HEADER, verbose_level, "FrameAspect: %d:%d Framewidth: %d Frameheight: %d\n",
- vprp->dwFrameAspectRatio >> 16, vprp->dwFrameAspectRatio & 0xffff,
- vprp->dwFrameWidthInPixels, vprp->dwFrameHeightInLines);
- mp_msg(MSGT_HEADER, verbose_level, "Fields: %d\n", vprp->nbFieldPerFrame);
- for (i=0; i<vprp->nbFieldPerFrame; i++) {
- VIDEO_FIELD_DESC *vfd = &vprp->FieldInfo[i];
- mp_msg(MSGT_HEADER, verbose_level, " == Field %d description ==\n", i);
- mp_msg(MSGT_HEADER, verbose_level, " CompressedBMHeight: %d CompressedBMWidth: %d\n",
- vfd->CompressedBMHeight, vfd->CompressedBMWidth);
- mp_msg(MSGT_HEADER, verbose_level, " ValidBMHeight: %d ValidBMWidth: %d\n",
- vfd->ValidBMHeight, vfd->ValidBMWidth);
- mp_msg(MSGT_HEADER, verbose_level, " ValidBMXOffset: %d ValidBMYOffset: %d\n",
- vfd->ValidBMXOffset, vfd->ValidBMYOffset);
- mp_msg(MSGT_HEADER, verbose_level, " VideoXOffsetInT: %d VideoYValidStartLine: %d\n",
- vfd->VideoXOffsetInT, vfd->VideoYValidStartLine);
- }
- mp_msg(MSGT_HEADER, verbose_level, "=======================================\n");
-}
-
-void print_index(AVIINDEXENTRY *idx, int idx_size, int verbose_level){
- int i;
- unsigned int pos[256];
- unsigned int num[256];
- memset(pos, 0, sizeof(pos));
- memset(num, 0, sizeof(num));
- for(i=0;i<idx_size;i++){
- int id=avi_stream_id(idx[i].ckid);
- if(id<0 || id>255) id=255;
- mp_msg(MSGT_HEADER, verbose_level, "%5d: %.4s %4X %016"PRIX64" len:%6"PRId32" pos:%7d->%7.3f %7d->%7.3f\n",i,
- (char *)&idx[i].ckid,
- (unsigned int)idx[i].dwFlags&0xffff,
- (uint64_t)AVI_IDX_OFFSET(&idx[i]),
-// idx[i].dwChunkOffset+demuxer->movi_start,
- idx[i].dwChunkLength,
- pos[id],(float)pos[id]/18747.0f,
- num[id],(float)num[id]/23.976f
- );
- pos[id]+=idx[i].dwChunkLength;
- ++num[id];
- }
-}
-
-void print_avistdindex_chunk(avistdindex_chunk *h, int verbose_level){
- mp_msg (MSGT_HEADER, verbose_level, "====== AVI Standard Index Header ========\n");
- mp_msg (MSGT_HEADER, verbose_level, " FCC (%.4s) dwSize (%d) wLongsPerEntry(%d)\n", h->fcc, h->dwSize, h->wLongsPerEntry);
- mp_msg (MSGT_HEADER, verbose_level, " bIndexSubType (%d) bIndexType (%d)\n", h->bIndexSubType, h->bIndexType);
- mp_msg (MSGT_HEADER, verbose_level, " nEntriesInUse (%d) dwChunkId (%.4s)\n", h->nEntriesInUse, h->dwChunkId);
- mp_msg (MSGT_HEADER, verbose_level, " qwBaseOffset (0x%"PRIX64") dwReserved3 (%d)\n", h->qwBaseOffset, h->dwReserved3);
- mp_msg (MSGT_HEADER, verbose_level, "===========================\n");
-}
-void print_avisuperindex_chunk(avisuperindex_chunk *h, int verbose_level){
- mp_msg (MSGT_HEADER, verbose_level, "====== AVI Super Index Header ========\n");
- mp_msg (MSGT_HEADER, verbose_level, " FCC (%.4s) dwSize (%d) wLongsPerEntry(%d)\n", h->fcc, h->dwSize, h->wLongsPerEntry);
- mp_msg (MSGT_HEADER, verbose_level, " bIndexSubType (%d) bIndexType (%d)\n", h->bIndexSubType, h->bIndexType);
- mp_msg (MSGT_HEADER, verbose_level, " nEntriesInUse (%d) dwChunkId (%.4s)\n", h->nEntriesInUse, h->dwChunkId);
- mp_msg (MSGT_HEADER, verbose_level, " dwReserved[0] (%d) dwReserved[1] (%d) dwReserved[2] (%d)\n",
- h->dwReserved[0], h->dwReserved[1], h->dwReserved[2]);
- mp_msg (MSGT_HEADER, verbose_level, "===========================\n");
-}
diff --git a/demux/aviprint.h b/demux/aviprint.h
deleted file mode 100644
index 86123b7725..0000000000
--- a/demux/aviprint.h
+++ /dev/null
@@ -1,35 +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_AVIPRINT_H
-#define MPLAYER_AVIPRINT_H
-
-#include "ms_hdr.h"
-#include "aviheader.h"
-
-void print_avih_flags(MainAVIHeader *h, int verbose_level);
-void print_avih(MainAVIHeader *h, int verbose_level);
-void print_strh(AVIStreamHeader *h, int verbose_level);
-void print_wave_header(WAVEFORMATEX *h, int verbose_level);
-void print_video_header(BITMAPINFOHEADER *h, int verbose_level);
-void print_vprp(VideoPropHeader *vprp, int verbose_level);
-void print_index(AVIINDEXENTRY *idx, int idx_size, int verbose_level);
-void print_avistdindex_chunk(avistdindex_chunk *h, int verbose_level);
-void print_avisuperindex_chunk(avisuperindex_chunk *h, int verbose_level);
-
-#endif /* MPLAYER_AVIPRINT_H */
diff --git a/demux/demux.c b/demux/demux.c
index a5d3211b0a..3f5851e5b6 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -55,18 +55,9 @@ extern const demuxer_desc_t demuxer_desc_rawaudio;
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_asf;
extern const demuxer_desc_t demuxer_desc_matroska;
extern const demuxer_desc_t demuxer_desc_lavf;
extern const demuxer_desc_t demuxer_desc_mng;
-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_gxf;
-extern const demuxer_desc_t demuxer_desc_mpeg_es;
-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_mpeg_ts;
extern const demuxer_desc_t demuxer_desc_libass;
extern const demuxer_desc_t demuxer_desc_subreader;
@@ -86,18 +77,9 @@ const demuxer_desc_t *const demuxer_list[] = {
&demuxer_desc_matroska,
&demuxer_desc_lavf,
&demuxer_desc_subreader,
- &demuxer_desc_avi,
- &demuxer_desc_asf,
#ifdef CONFIG_MNG
&demuxer_desc_mng,
#endif
- &demuxer_desc_mpeg_ps,
- &demuxer_desc_mpeg_pes,
- &demuxer_desc_mpeg_gxf,
- &demuxer_desc_mpeg_es,
- &demuxer_desc_mpeg4_es,
- &demuxer_desc_h264_es,
- &demuxer_desc_mpeg_ts,
// auto-probe last, because it checks file-extensions only
&demuxer_desc_mf,
/* Please do not add any new demuxers here. If you want to implement a new
@@ -234,7 +216,6 @@ static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer,
.stream_type = type,
.id = id,
.demuxer = demuxer,
- .asf_seq = -1,
};
return ds;
}
@@ -357,34 +338,6 @@ static void free_sh_stream(struct sh_stream *sh)
{
}
-sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid)
-{
- if (id > MAX_S_STREAMS - 1 || id < 0) {
- mp_msg(MSGT_DEMUXER, MSGL_WARN,
- "Requested sub stream id overflow (%d > %d)\n", id,
- MAX_S_STREAMS);
- return NULL;
- }
- if (demuxer->s_streams[id])
- mp_msg(MSGT_DEMUXER, MSGL_WARN, "Sub stream %i redefined\n", id);
- else {
- new_sh_stream_id(demuxer, STREAM_SUB, id, sid);
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid);
- }
- return demuxer->s_streams[id];
-}
-
-struct sh_sub *new_sh_sub_sid_lang(struct demuxer *demuxer, int id, int sid,
- const char *lang)
-{
- struct sh_sub *sh = new_sh_sub_sid(demuxer, id, sid);
- if (lang && lang[0] && strcmp(lang, "und")) {
- sh->gsh->lang = talloc_strdup(sh, lang);
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", sid, lang);
- }
- return sh;
-}
-
static void free_sh_sub(sh_sub_t *sh)
{
mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_sub at %p\n", sh);
@@ -610,9 +563,7 @@ static bool demux_check_queue_full(demuxer_t *demux)
"packet queue (video: %d packets in %d bytes, audio: %d "
"packets in %d bytes).\n", vpacks, vbytes, apacks, abytes);
mp_tmsg(MSGT_DEMUXER, MSGL_HINT, "Maybe you are playing a non-"
- "interleaved stream/file or the codec failed?\nFor AVI files, "
- "try to force non-interleaved mode with the "
- "--demuxer=avi --avi-ni options.\n");
+ "interleaved stream/file or the codec failed?\n");
}
demux->warned_queue_overflow = true;
@@ -716,65 +667,6 @@ int ds_fill_buffer(demux_stream_t *ds)
return 0;
}
-int demux_read_data(demux_stream_t *ds, unsigned char *mem, int len)
-{
- int x;
- int bytes = 0;
- while (len > 0) {
- x = ds->buffer_size - ds->buffer_pos;
- if (x == 0) {
- if (!ds_fill_buffer(ds))
- return bytes;
- } else {
- if (x > len)
- x = len;
- if (mem)
- memcpy(mem + bytes, &ds->buffer[ds->buffer_pos], x);
- bytes += x;
- len -= x;
- ds->buffer_pos += x;
- }
- }
- return bytes;
-}
-
-/**
- * \brief read data until the given 3-byte pattern is encountered, up to maxlen
- * \param mem memory to read data into, may be NULL to discard data
- * \param maxlen maximum number of bytes to read
- * \param read number of bytes actually read
- * \param pattern pattern to search for (lowest 8 bits are ignored)
- * \return whether pattern was found
- */
-int demux_pattern_3(demux_stream_t *ds, unsigned char *mem, int maxlen,
- int *read, uint32_t pattern)
-{
- register uint32_t head = 0xffffff00;
- register uint32_t pat = pattern & 0xffffff00;
- int total_len = 0;
- do {
- register unsigned char *ds_buf = &ds->buffer[ds->buffer_size];
- int len = ds->buffer_size - ds->buffer_pos;
- register long pos = -len;
- if (unlikely(pos >= 0)) { // buffer is empty
- ds_fill_buffer(ds);
- continue;
- }
- do {
- head |= ds_buf[pos];
- head <<= 8;
- } while (++pos && head != pat);
- len += pos;
- if (total_len + len > maxlen)
- len = maxlen - total_len;
- len = demux_read_data(ds, mem ? &mem[total_len] : NULL, len);
- total_len += len;
- } while ((head != pat || total_len < 3) && total_len < maxlen && !ds->eof);
- if (read)
- *read = total_len;
- return total_len >= 3 && head == pat;
-}
-
void ds_free_packs(demux_stream_t *ds)
{
demux_packet_t *dp = ds->first;
@@ -783,11 +675,6 @@ void ds_free_packs(demux_stream_t *ds)
free_demux_packet(dp);
dp = dn;
}
- if (ds->asf_packet) {
- // free unfinished .asf fragments:
- free_demux_packet(ds->asf_packet);
- ds->asf_packet = NULL;
- }
ds->first = ds->last = NULL;
ds->packs = 0; // !!!!!
ds->bytes = 0;
@@ -1019,22 +906,6 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts,
if (demuxer_type)
file_format = demuxer_type;
- // 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);
@@ -1099,14 +970,7 @@ int demux_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay,
int flags)
{
if (!demuxer->seekable) {
- if (demuxer->file_format == DEMUXER_TYPE_AVI)
- mp_tmsg(MSGT_SEEK, MSGL_WARN, "Cannot seek in raw AVI streams. (Index required, try with the -idx switch.)\n");
-#ifdef CONFIG_TV
- else if (demuxer->file_format == DEMUXER_TYPE_TV)
- mp_tmsg(MSGT_SEEK, MSGL_WARN, "TV input is not seekable! (Seeking will probably be for changing channels ;)\n");
-#endif
- else
- mp_tmsg(MSGT_SEEK, MSGL_WARN, "Cannot seek in this file.\n");
+ mp_tmsg(MSGT_SEEK, MSGL_WARN, "Cannot seek in this file.\n");
return 0;
}
diff --git a/demux/demux.h b/demux/demux.h
index 20e6ba7a66..df73ddd4ee 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -32,42 +32,17 @@
struct MPOpts;
-#if (__GNUC__ >= 3)
-#define likely(x) __builtin_expect((x) != 0, 1)
-#define unlikely(x) __builtin_expect((x) != 0, 0)
-#else
-#define likely(x) (x)
-#define unlikely(x) (x)
-#endif
-
#define MAX_PACKS 4096
#define MAX_PACK_BYTES 0x8000000 // 128 MiB
enum demuxer_type {
DEMUXER_TYPE_UNKNOWN = 0,
- DEMUXER_TYPE_MPEG_PS,
- DEMUXER_TYPE_AVI,
- DEMUXER_TYPE_AVI_NI,
- DEMUXER_TYPE_AVI_NINI,
- DEMUXER_TYPE_ASF,
DEMUXER_TYPE_TV,
- DEMUXER_TYPE_Y4M,
DEMUXER_TYPE_MF,
DEMUXER_TYPE_RAWAUDIO,
DEMUXER_TYPE_RAWVIDEO,
- DEMUXER_TYPE_MPEG_ES,
- DEMUXER_TYPE_MPEG4_ES,
- DEMUXER_TYPE_H264_ES,
- DEMUXER_TYPE_MPEG_PES,
- DEMUXER_TYPE_MPEG_GXF,
- DEMUXER_TYPE_GIF,
- DEMUXER_TYPE_MPEG_TS,
DEMUXER_TYPE_MATROSKA,
DEMUXER_TYPE_LAVF,
- DEMUXER_TYPE_NSV,
- DEMUXER_TYPE_AVS,
- DEMUXER_TYPE_AAC,
- DEMUXER_TYPE_MPC,
DEMUXER_TYPE_MNG,
DEMUXER_TYPE_EDL,
DEMUXER_TYPE_CUE,
@@ -134,21 +109,10 @@ typedef struct demux_stream {
demux_packet_t *current; // needed for refcounting of the buffer
int id; // stream ID (for multiple audio/video streams)
struct demuxer *demuxer; // parent demuxer structure (stream handler)
-// ---- asf -----
- struct demux_packet *asf_packet; // read asf fragments here
- int asf_seq;
// ---- stream header ----
void *sh; // points to sh_audio or sh_video
} demux_stream_t;
-typedef struct demuxer_info {
- char *name;
- char *author;
- char *encoder;
- char *comments;
- char *copyright;
-} demuxer_info_t;
-
#define MAX_SH_STREAMS 256
#define MAX_A_STREAMS MAX_SH_STREAMS
#define MAX_V_STREAMS MAX_SH_STREAMS
@@ -300,15 +264,6 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp);
#define SIZE_MAX ((size_t)-1)
#endif
-static inline void *realloc_struct(void *ptr, size_t nmemb, size_t size)
-{
- if (nmemb > SIZE_MAX / size) {
- free(ptr);
- return NULL;
- }
- return realloc(ptr, nmemb * size);
-}
-
void free_demuxer(struct demuxer *demuxer);
int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream,
@@ -330,17 +285,6 @@ static inline int ds_tell_pts(struct demux_stream *ds)
return (ds->pts_bytes - ds->buffer_size) + ds->buffer_pos;
}
-int demux_read_data(struct demux_stream *ds, unsigned char *mem, int len);
-int demux_pattern_3(struct demux_stream *ds, unsigned char *mem, int maxlen,
- int *read, uint32_t pattern);
-
-#define demux_peekc(ds) ( \
- (likely(ds->buffer_pos<ds->buffer_size)) ? ds->buffer[ds->buffer_pos] \
- : ((unlikely(!ds_fill_buffer(ds))) ? (-1) : ds->buffer[ds->buffer_pos]))
-#define demux_getc(ds) ( \
- (likely(ds->buffer_pos<ds->buffer_size)) ? ds->buffer[ds->buffer_pos++] \
- : ((unlikely(!ds_fill_buffer(ds))) ? (-1) : ds->buffer[ds->buffer_pos++]))
-
void ds_free_packs(struct demux_stream *ds);
int ds_get_packet(struct demux_stream *ds, unsigned char **start);
int ds_get_packet_pts(struct demux_stream *ds, unsigned char **start,
@@ -352,16 +296,6 @@ int ds_parse(struct demux_stream *sh, uint8_t **buffer, int *len, double pts,
int64_t pos);
void ds_clear_parser(struct demux_stream *sh);
-static inline int avi_stream_id(unsigned int id)
-{
- unsigned char a, b;
- a = id - '0';
- b = (id >> 8) - '0';
- if (a>9 || b>9)
- return 100; // invalid ID
- return a * 10 + b;
-}
-
struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream,
int file_format, int aid, int vid, int sid,
char *filename);
@@ -376,11 +310,6 @@ void demux_flush(struct demuxer *demuxer);
int demux_seek(struct demuxer *demuxer, float rel_seek_secs, float audio_delay,
int flags);
-// AVI demuxer params:
-extern int index_mode; // -1=untouched 0=don't use index 1=use (generate) index
-extern int force_ni;
-extern int pts_from_bps;
-
int demux_info_add(struct demuxer *demuxer, const char *opt, const char *param);
int demux_info_add_bstr(struct demuxer *demuxer, struct bstr opt,
struct bstr param);
diff --git a/demux/demux_asf.c b/demux/demux_asf.c
deleted file mode 100644
index f800e09dc3..0000000000
--- a/demux/demux_asf.c
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * ASF file parser for DEMUXER v0.3
- * copyright (c) 2001 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 <limits.h>
-
-#include <libavutil/intreadwrite.h>
-
-#include "config.h"
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "asf.h"
-#include "asfheader.h"
-#include "demux.h"
-#include "audio/decode/dec_audio.h"
-
-// based on asf file-format doc by Eugene [http://divx.euro.ru]
-
-/**
- * \brief reads int stored in number of bytes given by len
- * \param ptr pointer to read from, is incremented appropriately
- * \param len lowest 2 bits indicate number of bytes to read
- * \param def default value to return if len is invalid
- */
-static inline unsigned read_varlen(uint8_t **ptr, int len, int def) {
- const uint8_t *p = *ptr;
- len &= 3;
- switch (len) {
- case 1: *ptr += 1; return *p;
- case 2: *ptr += 2; return AV_RL16(p);
- case 3: *ptr += 4; return AV_RL32(p);
- }
- return def;
-}
-
-/**
- * \brief checks if there is enough data to read the bytes given by len
- * \param ptr pointer to read from
- * \param endptr pointer to the end of the buffer
- * \param len lowest 2 bits indicate number of bytes to read
- */
-static inline int check_varlen(uint8_t *ptr, uint8_t *endptr, int len) {
- return len&3 ? ptr + (1<<((len&3) - 1)) <= endptr : 1;
-}
-
-static void asf_descrambling(unsigned char **src,unsigned len, struct asf_priv* asf){
- unsigned char *dst;
- unsigned char *s2=*src;
- unsigned i=0,x,y;
- if (len > UINT_MAX - MP_INPUT_BUFFER_PADDING_SIZE)
- return;
- dst = malloc(len + MP_INPUT_BUFFER_PADDING_SIZE);
- while(len>=asf->scrambling_h*asf->scrambling_w*asf->scrambling_b+i){
-// mp_msg(MSGT_DEMUX,MSGL_DBG4,"descrambling! (w=%d b=%d)\n",w,asf_scrambling_b);
- //i+=asf_scrambling_h*asf_scrambling_w;
- for(x=0;x<asf->scrambling_w;x++)
- for(y=0;y<asf->scrambling_h;y++){
- memcpy(dst+i,s2+(y*asf->scrambling_w+x)*asf->scrambling_b,asf->scrambling_b);
- i+=asf->scrambling_b;
- }
- s2+=asf->scrambling_h*asf->scrambling_w*asf->scrambling_b;
- }
- //if(i<len) memcpy(dst+i,src+i,len-i);
- free(*src);
- *src = dst;
-}
-
-/*****************************************************************
- * \brief initializes asf private data
- *
- */
-static void init_priv (struct asf_priv* asf){
- asf->last_vid_seq=-1;
- asf->vid_ext_timing_index=-1;
- asf->aud_ext_timing_index=-1;
- asf->vid_ext_frame_index=-1;
-}
-
-static void demux_asf_append_to_packet(demux_packet_t* dp,unsigned char *data,int len,int offs)
-{
- if(dp->len!=offs && offs!=-1) mp_msg(MSGT_DEMUX,MSGL_V,"warning! fragment.len=%d BUT next fragment offset=%d \n",dp->len,offs);
- size_t old_len = dp->len;
- resize_demux_packet(dp, dp->len + len);
- memcpy(dp->buffer + old_len, data, len);
-}
-
-static int demux_asf_read_packet(demuxer_t *demux,unsigned char *data,int len,int id,int seq,uint64_t time,unsigned short dur,int offs,int keyframe){
- struct asf_priv* asf = demux->priv;
- demux_stream_t *ds=NULL;
- int close_seg=0;
-
- mp_dbg(MSGT_DEMUX,MSGL_DBG4,"demux_asf.read_packet: id=%d seq=%d len=%d\n",id,seq,len);
-
- if(demux->video->id==-1)
- if(demux->v_streams[id])
- demux->video->id=id;
-
- if(demux->audio->id==-1)
- if(demux->a_streams[id])
- demux->audio->id=id;
-
- if(id==demux->audio->id){
- // audio
- ds=demux->audio;
- if(!ds->sh){
- ds->sh=demux->a_streams[id];
- mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF audio ID = %d\n",ds->id);
- }
- } else
- if(id==demux->video->id){
- // video
- ds=demux->video;
- if(!ds->sh){
- ds->sh=demux->v_streams[id];
- mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF video ID = %d\n",ds->id);
- }
- }
-
- if(ds){
- if(ds->asf_packet){
- demux_packet_t* dp=ds->asf_packet;
-
- if (ds==demux->video && asf->asf_is_dvr_ms) {
- if (asf->new_vid_frame_seg) {
- dp->pos=demux->filepos;
- close_seg = 1;
- } else seq = ds->asf_seq;
- } else close_seg = ds->asf_seq!=seq;
-
- if(close_seg){
- // closed segment, finalize packet:
- if(ds==demux->audio)
- if(asf->scrambling_h>1 && asf->scrambling_w>1 && asf->scrambling_b>0)
- asf_descrambling(&ds->asf_packet->buffer,ds->asf_packet->len,asf);
- ds_add_packet(ds,ds->asf_packet);
- ds->asf_packet=NULL;
- } else {
- // append data to it!
- demux_asf_append_to_packet(dp,data,len,offs);
- // we are ready now.
- return 1;
- }
- }
- // create new packet:
- { demux_packet_t* dp;
- if(offs>0){
- mp_msg(MSGT_DEMUX,MSGL_V,"warning! broken fragment, %d bytes missing \n",offs);
- return 0;
- }
- dp=new_demux_packet(len);
- memcpy(dp->buffer,data,len);
- if (asf->asf_is_dvr_ms)
- dp->pts=time*0.0000001;
- else
- dp->pts=time*0.001;
- dp->keyframe = keyframe;
-// if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur);
- dp->pos=demux->filepos;
- ds->asf_packet=dp;
- ds->asf_seq=seq;
- // we are ready now.
- return 1;
- }
- }
-
- return 0;
-}
-
-/*****************************************************************
- * \brief read the replicated data associated with each segment
- * \parameter pp reference to replicated data
- * \parameter id stream number
- * \parameter seq media object number
- * \parameter keyframe key frame indicator - set to zero if keyframe, non-zero otherwise
- * \parameter seg_time set to payload time when valid, if audio or new video frame payload, zero otherwise
- *
- */
-static void get_payload_extension_data(demuxer_t *demux, unsigned char** pp, unsigned char id, unsigned int seq, int *keyframe, uint64_t *seg_time){
- struct asf_priv* asf = demux->priv;
- uint64_t payload_time = -1; //100ns units
- int i, ext_max, ext_timing_index;
- uint8_t *pi = *pp+4;
-
- if(demux->video->id==-1)
- if(demux->v_streams[id])
- demux->video->id=id;
-
- if(demux->audio->id==-1)
- if(demux->a_streams[id])
- demux->audio->id=id;
-
- if (id!=demux->video->id && id!=demux->audio->id) return;
-
- if (id==demux->video->id) {
- ext_max = asf->vid_repdata_count;
- ext_timing_index = asf->vid_ext_timing_index;
- } else {
- ext_max = asf->aud_repdata_count;
- ext_timing_index = asf->aud_ext_timing_index;
- }
-
- *seg_time=0.0;
- asf->new_vid_frame_seg = 0;
-
- for (i=0; i<ext_max; i++) {
- uint16_t payextsize;
- uint8_t segment_marker;
-
- if (id==demux->video->id)
- payextsize = asf->vid_repdata_sizes[i];
- else
- payextsize = asf->aud_repdata_sizes[i];
-
- if (payextsize == 65535) {
- payextsize = AV_RL16(pi);
- pi+=2;
- }
-
- // if this is the timing info extension then read the payload time
- if (i == ext_timing_index)
- payload_time = AV_RL64(pi+8);
-
- // if this is the video frame info extension then
- // set the keyframe indicator, the 'new frame segment' indicator
- // and (initially) the 'frame time'
- if (i == asf->vid_ext_frame_index && id==demux->video->id) {
- segment_marker = pi[0];
- // Known video stream segment_marker values that
- // contain useful information:
- //
- // NTSC/ATSC (29.97fps): 0X4A 01001010
- // 0X4B 01001011
- // 0X49 01001001
- //
- // PAL/ATSC (25fps): 0X3A 00111010
- // 0X3B 00111011
- // 0X39 00111001
- //
- // ATSC progressive (29.97fps): 0X7A 01111010
- // 0X7B 01111011
- // 0X79 01111001
- // 11111111
- // ^ this is new video frame marker
- //
- // ^^^^ these bits indicate the framerate
- // 0X4 is 29.97i, 0X3 is 25i, 0X7 is 29.97p, ???=25p
- //
- // ^^^ these bits indicate the frame type:
- // 001 means I-frame
- // 010 and 011 probably mean P and B
-
- asf->new_vid_frame_seg = (0X08 & segment_marker) && seq != asf->last_vid_seq;
-
- if (asf->new_vid_frame_seg) asf->last_vid_seq = seq;
-
- if (asf->avg_vid_frame_time == 0) {
- // set the average frame time initially (in 100ns units).
- // This is based on what works for known samples.
- // It can be extended if more samples of different types can be obtained.
- if (((segment_marker & 0XF0) >> 4) == 4) {
- asf->avg_vid_frame_time = (uint64_t)((1.001 / 30.0) * 10000000.0);
- asf->know_frame_time=1;
- } else if (((segment_marker & 0XF0) >> 4) == 3) {
- asf->avg_vid_frame_time = (uint64_t)(0.04 * 10000000.0);
- asf->know_frame_time=1;
- } else if (((segment_marker & 0XF0) >> 4) == 6) {
- asf->avg_vid_frame_time = (uint64_t)(0.02 * 10000000.0);
- asf->know_frame_time=1;
- } else if (((segment_marker & 0XF0) >> 4) == 7) {
- asf->avg_vid_frame_time = (uint64_t)((1.001 / 60.0) * 10000000.0);
- asf->know_frame_time=1;
- } else {
- // we dont know the frame time initially so
- // make a guess and then recalculate as we go.
- asf->avg_vid_frame_time = (uint64_t)((1.001 / 60.0) * 10000000.0);
- asf->know_frame_time=0;
- }
- }
- *keyframe = (asf->new_vid_frame_seg && (segment_marker & 0X07) == 1);
- }
- pi +=payextsize;
- }
-
- if (id==demux->video->id && asf->new_vid_frame_seg) {
- asf->vid_frame_ct++;
- // Some samples only have timings on key frames and
- // the rest contain non-cronological timestamps. Interpolating
- // the values between key frames works for all samples.
- if (*keyframe) {
- asf->found_first_key_frame=1;
- if (!asf->know_frame_time && asf->last_key_payload_time > 0) {
- // We dont know average frametime so recalculate.
- // Giving precedence to the 'weight' of the existing
- // average limits damage done to new value when there is
- // a sudden time jump which happens occasionally.
- asf->avg_vid_frame_time =
- (0.9 * asf->avg_vid_frame_time) +
- (0.1 * ((payload_time - asf->last_key_payload_time) / asf->vid_frame_ct));
- }
- asf->last_key_payload_time = payload_time;
- asf->vid_frame_ct = 1;
- *seg_time = payload_time;
- } else
- *seg_time = (asf->last_key_payload_time + (asf->avg_vid_frame_time * (asf->vid_frame_ct-1)));
- }
-
- if (id==demux->audio->id) {
- if (payload_time != -1)
- asf->last_aud_diff = payload_time - asf->last_aud_pts;
- asf->last_aud_pts += asf->last_aud_diff;
- *seg_time = asf->last_aud_pts;
- }
-}
-//static int num_elementary_packets100=0;
-//static int num_elementary_packets101=0;
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_asf_fill_buffer(demuxer_t *demux, demux_stream_t *ds){
- struct asf_priv* asf = demux->priv;
-
- demux->filepos=stream_tell(demux->stream);
- // Brodcast stream have movi_start==movi_end
- // Better test ?
- if((demux->movi_start < demux->movi_end) && (demux->filepos>=demux->movi_end)){
- demux->stream->eof=1;
- return 0;
- }
-
- stream_read(demux->stream,asf->packet,asf->packetsize);
- if(demux->stream->eof) return 0; // EOF
- if(asf->packetsize < 2) return 0; // Packet too short
-
- {
- unsigned char* p=asf->packet;
- unsigned char* p_end=asf->packet+asf->packetsize;
- unsigned char flags=p[0];
- unsigned char segtype=p[1];
- unsigned padding;
- unsigned plen;
- unsigned sequence av_unused;
- unsigned long time av_unused = 0;
- unsigned short duration=0;
-
- int segs=1;
- unsigned char segsizetype=0x80;
- int seg=-1;
-
- if( mp_msg_test(MSGT_DEMUX,MSGL_DBG2) ){
- int i;
- for(i=0;i<FFMIN(16, asf->packetsize);i++) printf(" %02X",asf->packet[i]);
- printf("\n");
- }
-
- // skip ECC data if present by testing bit 7 of flags
- // 1xxxbbbb -> ecc data present, skip bbbb byte(s)
- // 0xxxxxxx -> payload parsing info starts
- if (flags & 0x80)
- {
- p += (flags & 0x0f)+1;
- if (p+1 >= p_end) return 0; // Packet too short
- flags = p[0];
- segtype = p[1];
- }
-
- //if(segtype!=0x5d) printf("Warning! packet[4] != 0x5d \n");
-
- p+=2; // skip flags & segtype
-
- // Read packet size (plen):
- if(!check_varlen(p, p_end, flags>> 5)) return 0; // Not enough data
- plen = read_varlen(&p, flags >> 5, 0);
-
- // Read sequence:
- if(!check_varlen(p, p_end, flags>> 1)) return 0; // Not enough data
- sequence = read_varlen(&p, flags >> 1, 0);
-
- // Read padding size (padding):
- if(!check_varlen(p, p_end, flags>> 3)) return 0; // Not enough data
- padding = read_varlen(&p, flags >> 3, 0);
-
- if(((flags>>5)&3)!=0){
- // Explicit (absoulte) packet size
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Explicit packet size specified: %d \n",plen);
- if(plen>asf->packetsize) mp_msg(MSGT_DEMUX,MSGL_V,"Warning! plen>packetsize! (%d>%d) \n",plen,asf->packetsize);
- } else {
- // Padding (relative) size
- plen=asf->packetsize-padding;
- }
-
- // Read time & duration:
- if (p+5 >= p_end) return 0; // Packet too short
- time = AV_RL32(p); p+=4;
- duration = AV_RL16(p); p+=2;
-
- // Read payload flags:
- if(flags&1){
- // multiple sub-packets
- if (p >= p_end) return 0; // Packet too short
- segsizetype=p[0]>>6;
- segs=p[0] & 0x3F;
- ++p;
- }
- mp_dbg(MSGT_DEMUX,MSGL_DBG4,"%08"PRIu64": flag=%02X segs=%d seq=%u plen=%u pad=%u time=%ld dur=%d\n",
- (uint64_t)demux->filepos,flags,segs,sequence,plen,padding,time,duration);
-
- for(seg=0;seg<segs;seg++){
- //ASF_segmhdr_t* sh;
- unsigned char streamno;
- unsigned int seq;
- unsigned int x; // offset or timestamp
- unsigned int rlen;
- //
- int len;
- uint64_t time2=0;
- int keyframe=0;
-
- if(p>=p_end) {
- mp_msg(MSGT_DEMUX,MSGL_V,"Warning! invalid packet 1, aborting parsing...\n");
- break;
- }
-
- if( mp_msg_test(MSGT_DEMUX,MSGL_DBG2) ){
- int i;
- printf("seg %d:",seg);
- for(i=0;i<FFMIN(16, p_end - p);i++) printf(" %02X",p[i]);
- printf("\n");
- }
-
- streamno=p[0]&0x7F;
- if(p[0]&0x80) keyframe=1;
- p++;
-
- // Read media object number (seq):
- if(!check_varlen(p, p_end, segtype >> 4)) break; // Not enough data
- seq = read_varlen(&p, segtype >> 4, 0);
-
- // Read offset or timestamp:
- if(!check_varlen(p, p_end, segtype >> 2)) break; // Not enough data
- x = read_varlen(&p, segtype >> 2, 0);
-
- // Read replic.data len:
- if(!check_varlen(p, p_end, segtype)) break; // Not enough data
- rlen = read_varlen(&p, segtype, 0);
-
-// printf("### rlen=%d \n",rlen);
- if (rlen > p_end - p) {
- mp_msg(MSGT_DEMUX, MSGL_V, "invalid rlen=%u\n", rlen);
- break;
- }
-
- switch(rlen){
- case 0x01: // 1 = special, means grouping
- //printf("grouping: %02X \n",p[0]);
- ++p; // skip PTS delta
- break;
- default:
- if(rlen>=8){
- p+=4; // skip object size
- if (p+3 >= p_end) break; // Packet too short
- time2=AV_RL32(p); // read PTS
- if (asf->asf_is_dvr_ms)
- get_payload_extension_data(demux, &p, streamno, seq, &keyframe, &time2);
- p+=rlen-4;
- } else {
- mp_msg(MSGT_DEMUX,MSGL_V,"unknown segment type (rlen): 0x%02X \n",rlen);
- time2=0; // unknown
- p+=rlen;
- }
- }
-
- if(flags&1){
- // multiple segments
- if(!check_varlen(p, p_end, segsizetype)) break; // Not enough data
- len = read_varlen(&p, segsizetype, plen-(p-asf->packet));
- } else {
- // single segment
- len=plen-(p-asf->packet);
- }
- if(len<0 || (p+len)>p_end){
- mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! segment len=%d\n",len);
- len = p_end - p;
- }
- mp_dbg(MSGT_DEMUX,MSGL_DBG4," seg #%d: streamno=%d seq=%d type=%02X len=%d\n",seg,streamno,seq,rlen,len);
-
- switch(rlen){
- case 0x01:
- // GROUPING:
- //printf("ASF_parser: warning! grouping (flag=1) not yet supported!\n",len);
- //printf(" total: %d \n",len);
- while(len>0){
- int len2=p[0];
- p++;
- //printf(" group part: %d bytes\n",len2);
- if(len2 > len - 1 || len2 < 0) break; // Not enough data
- len2 = FFMIN(len2, asf->packetsize);
- demux_asf_read_packet(demux,p,len2,streamno,seq,x,duration,-1,keyframe);
- p+=len2;
- len-=len2+1;
- ++seq;
- }
- if(len!=0){
- mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! groups total != len\n");
- }
- break;
- default:
- // NO GROUPING:
- //printf("fragment offset: %d \n",sh->x);
- if (len <= 0) break;
- if (!asf->asf_is_dvr_ms || asf->found_first_key_frame) {
- len = FFMIN(len, asf->packetsize);
- demux_asf_read_packet(demux,p,len,streamno,seq,time2,duration,x,keyframe);
- }
- p+=len;
- break;
- }
-
- } // for segs
- return 1; // success
- }
-
- mp_msg(MSGT_DEMUX,MSGL_V,"%08"PRIX64": UNKNOWN TYPE %02X %02X %02X %02X %02X...\n",(int64_t)demux->filepos,asf->packet[0],asf->packet[1],asf->packet[2],asf->packet[3],asf->packet[4]);
- return 0;
-}
-
-#include "stheader.h"
-
-static void demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
- struct asf_priv* asf = demuxer->priv;
- 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;
-
- //FIXME: OFF_T - didn't test ASF case yet (don't have a large asf...)
- //FIXME: reports good or bad to steve@daviesfam.org please
-
- //================= seek in ASF ==========================
- float p_rate=asf->packetrate; // packets / sec
- int64_t rel_seek_packs=(flags&SEEK_FACTOR)? // FIXME: int may be enough?
- (rel_seek_secs*(demuxer->movi_end-demuxer->movi_start)/asf->packetsize):
- (rel_seek_secs*p_rate);
- int64_t rel_seek_bytes=rel_seek_packs*asf->packetsize;
- int64_t newpos;
- //printf("ASF: packs: %d duration: %d \n",(int)fileh.packets,*((int*)&fileh.duration));
-// printf("ASF_seek: %d secs -> %d packs -> %d bytes \n",
-// rel_seek_secs,rel_seek_packs,rel_seek_bytes);
- newpos=((flags&SEEK_ABSOLUTE)?demuxer->movi_start:demuxer->filepos)+rel_seek_bytes;
- if(newpos<0 || newpos<demuxer->movi_start) newpos=demuxer->movi_start;
-// printf("\r -- asf: newpos=%d -- \n",newpos);
- stream_seek(demuxer->stream,newpos);
-
- if (asf->asf_is_dvr_ms) asf->dvr_last_vid_pts = 0.0f;
-
- if (d_video->id >= 0)
- ds_fill_buffer(d_video);
- if(sh_audio){
- ds_fill_buffer(d_audio);
- }
-
- if (d_video->id >= 0)
- while(1){
- if(sh_audio && !d_audio->eof){
- float a_pts=d_audio->pts;
- a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
- // sync audio:
- if (d_video->pts > a_pts){
- skip_audio_frame(sh_audio);
-// if(!ds_fill_buffer(d_audio)) sh_audio=NULL; // skip audio. EOF?
- continue;
- }
- }
- if (d_video->keyframe)
- break;
- if(!ds_fill_buffer(d_video)) break; // skip frame. EOF?
- }
-
-
-}
-
-static int demux_asf_control(demuxer_t *demuxer,int cmd, void *arg){
- struct asf_priv* asf = demuxer->priv;
-/* 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;
-*/
- switch(cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- *((double *)arg)=asf->movielength;
- return DEMUXER_CTRL_OK;
-
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-
-static demuxer_t* demux_open_asf(demuxer_t* demuxer)
-{
- struct asf_priv* asf = demuxer->priv;
- sh_video_t *sh_video=NULL;
-
- //---- ASF header:
- if(!asf) return NULL;
- init_priv(asf);
- if (!read_asf_header(demuxer,asf))
- return NULL;
- stream_seek(demuxer->stream,demuxer->movi_start);
-// demuxer->idx_pos=0;
-// demuxer->endpos=avi_header.movi_end;
- if(demuxer->video->id != -2) {
- if(!ds_fill_buffer(demuxer->video)){
- mp_msg(MSGT_DEMUXER, MSGL_WARN, "ASF: %s",
- mp_gtext("No video stream found.\n"));
- demuxer->video->sh=NULL;
- //printf("ASF: missing video stream!? contact the author, it may be a bug :(\n");
- } else {
- sh_video=demuxer->video->sh;
- sh_video->fps=1000.0f; sh_video->frametime=0.001f;
-
- if (asf->asf_is_dvr_ms) {
- sh_video->bih->biWidth = 0;
- sh_video->bih->biHeight = 0;
- }
- }
- }
-
- if(demuxer->audio->id!=-2){
- mp_tmsg(MSGT_DEMUXER,MSGL_V,"ASF: Searching for audio stream (id:%d).\n",demuxer->audio->id);
- if(!ds_fill_buffer(demuxer->audio)){
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "ASF: %s",
- mp_gtext("No audio stream found -> no sound.\n"));
- demuxer->audio->sh=NULL;
- }
- }
- if(!demuxer->stream->seek)
- demuxer->seekable=0;
-
- return demuxer;
-}
-
-
-static void demux_close_asf(demuxer_t *demuxer) {
- struct asf_priv* asf = demuxer->priv;
-
- if (!asf) return;
-
- free(asf->aud_repdata_sizes);
- free(asf->vid_repdata_sizes);
- free(asf->packet);
- free(asf);
-}
-
-const demuxer_desc_t demuxer_desc_asf = {
- "ASF demuxer",
- "asf",
- "ASF",
- "A'rpi",
- "ASF, WMV, WMA",
- DEMUXER_TYPE_ASF,
- 1, // safe autodetect
- asf_check_header,
- demux_asf_fill_buffer,
- demux_open_asf,
- demux_close_asf,
- demux_seek_asf,
- demux_asf_control
-};
diff --git a/demux/demux_avi.c b/demux/demux_avi.c
deleted file mode 100644
index a07f022cde..0000000000
--- a/demux/demux_avi.c
+++ /dev/null
@@ -1,899 +0,0 @@
-/*
- * AVI file parser for DEMUXER v2.9
- * Copyright (c) 2001 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 "config.h"
-#include "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "demux.h"
-#include "stheader.h"
-#include "aviheader.h"
-
-extern const demuxer_desc_t demuxer_desc_avi_ni;
-extern const demuxer_desc_t demuxer_desc_avi_nini;
-
-// PTS: 0=interleaved 1=BPS-based
-int pts_from_bps=1;
-
-static void update_audio_block_size(demuxer_t *demux)
-{
- avi_priv_t *priv = demux->priv;
- sh_audio_t *sh = demux->audio->sh;
- if (!sh)
- return;
- priv->audio_block_size = sh->audio.dwSampleSize;
- if (sh->wf) {
- priv->audio_block_size = sh->wf->nBlockAlign;
- if (!priv->audio_block_size) {
- // for PCM audio we can calculate the blocksize:
- if (sh->format == 1)
- priv->audio_block_size = sh->wf->nChannels*(sh->wf->wBitsPerSample/8);
- else
- priv->audio_block_size = 1; // hope the best...
- } else {
- // workaround old mencoder bug:
- if (sh->audio.dwSampleSize == 1 && sh->audio.dwScale == 1 &&
- (sh->wf->nBlockAlign == 1152 || sh->wf->nBlockAlign == 576)) {
- mp_tmsg(MSGT_DEMUX,MSGL_WARN,"AVI: Working around CBR-MP3 nBlockAlign header bug!\n");
- priv->audio_block_size = 1;
- }
- }
- }
-}
-
-// Select ds from ID
-static demux_stream_t *demux_avi_select_stream(demuxer_t *demux,
- unsigned int id)
-{
- int stream_id=avi_stream_id(id);
-
-
- if(demux->video->id==-1)
- if(demux->v_streams[stream_id])
- demux->video->id=stream_id;
-
- if(demux->audio->id==-1)
- if(demux->a_streams[stream_id])
- demux->audio->id=stream_id;
-
- if(stream_id==demux->audio->id){
- if(!demux->audio->sh){
- demux->audio->sh=demux->a_streams[stream_id];
- mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI audio ID = %d\n",demux->audio->id);
- update_audio_block_size(demux);
- }
- return demux->audio;
- }
- if(stream_id==demux->video->id){
- if(!demux->video->sh){
- demux->video->sh=demux->v_streams[stream_id];
- mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI video ID = %d\n",demux->video->id);
- }
- return demux->video;
- }
- if(id!=mmioFOURCC('J','U','N','K')){
- // unknown
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"Unknown chunk: %.4s (%X)\n",(char *) &id,id);
- //abort();
- }
- return NULL;
-}
-
-static int valid_fourcc(unsigned int id){
- static const char valid[] = "0123456789abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
- unsigned char* fcc=(unsigned char*)(&id);
- return strchr(valid, fcc[0]) && strchr(valid, fcc[1]) &&
- strchr(valid, fcc[2]) && strchr(valid, fcc[3]);
-}
-
-static int valid_stream_id(unsigned int id) {
- unsigned char* fcc=(unsigned char*)(&id);
- return fcc[0] >= '0' && fcc[0] <= '9' && fcc[1] >= '0' && fcc[1] <= '9' &&
- ((fcc[2] == 'w' && fcc[3] == 'b') || (fcc[2] == 'd' && fcc[3] == 'c'));
-}
-
-static int choose_chunk_len(unsigned int len1,unsigned int len2){
- // len1 has a bit more priority than len2. len1!=len2
- // Note: this is a first-idea-logic, may be wrong. comments welcomed.
-
- // prefer small frames rather than 0
- if(!len1) return (len2>0x80000) ? len1 : len2;
- if(!len2) return (len1>0x100000) ? len2 : len1;
-
- // choose the smaller value:
- return (len1<len2)? len1 : len2;
-}
-
-static int demux_avi_read_packet(demuxer_t *demux,demux_stream_t *ds,unsigned int id,unsigned int len,int idxpos,int flags){
- avi_priv_t *priv=demux->priv;
- int skip;
- float pts=0;
-
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_avi.read_packet: %X\n",id);
-
- if(ds==demux->audio){
- if(priv->pts_corrected==0){
- if(priv->pts_has_video){
- // we have video pts now
- float delay=0;
- if(((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec)
- delay=(float)priv->pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec;
- mp_msg(MSGT_DEMUX,MSGL_V,"XXX initial v_pts=%5.3f a_pos=%d (%5.3f) \n",priv->avi_audio_pts,priv->pts_corr_bytes,delay);
- //priv->pts_correction=-priv->avi_audio_pts+delay;
- priv->pts_correction=delay-priv->avi_audio_pts;
- priv->avi_audio_pts+=priv->pts_correction;
- priv->pts_corrected=1;
- } else
- priv->pts_corr_bytes+=len;
- }
- if(pts_from_bps){
- pts = priv->audio_block_no *
- (float)((sh_audio_t*)demux->audio->sh)->audio.dwScale /
- (float)((sh_audio_t*)demux->audio->sh)->audio.dwRate;
- } else
- pts=priv->avi_audio_pts; //+priv->pts_correction;
- priv->avi_audio_pts=0;
- // update blockcount:
- priv->audio_block_no+=
- (len+priv->audio_block_size-1)/priv->audio_block_size;
- } else
- if(ds==demux->video){
- // video
- if(priv->skip_video_frames>0){
- // drop frame (seeking)
- --priv->skip_video_frames;
- ds=NULL;
- }
-
- pts = priv->avi_video_pts = priv->video_pack_no *
- (float)((sh_video_t*)demux->video->sh)->video.dwScale /
- (float)((sh_video_t*)demux->video->sh)->video.dwRate;
-
- priv->avi_audio_pts=priv->avi_video_pts+priv->pts_correction;
- priv->pts_has_video=1;
-
- if(ds) ++priv->video_pack_no;
-
- }
-
- skip=(len+1)&(~1); // total bytes in this chunk
-
- if(ds){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Read %d data bytes from packet %04X\n",len,id);
- ds_read_packet(ds,demux->stream,len,pts,idxpos,flags);
- skip-=len;
- }
- skip = FFMAX(skip, 0);
- if (avi_stream_id(id) > 99 && id != mmioFOURCC('J','U','N','K'))
- skip = FFMIN(skip, 65536);
- if(skip){
- mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Skipping %d bytes from packet %04X\n",skip,id);
- stream_skip(demux->stream,skip);
- }
- return ds?1:0;
-}
-
-static uint32_t avi_find_id(stream_t *stream) {
- uint32_t id = stream_read_dword_le(stream);
- if (!id) {
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Incomplete stream? Trying resync.\n");
- do {
- id = stream_read_dword_le(stream);
- if (stream_eof(stream)) return 0;
- } while (avi_stream_id(id) > 99);
- }
- return id;
-}
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_avi_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){
-avi_priv_t *priv=demux->priv;
-unsigned int id=0;
-unsigned int len;
-int ret=0;
-demux_stream_t *ds;
-
-do{
- int flags=1;
- AVIINDEXENTRY *idx=NULL;
- if(priv->idx_size>0 && priv->idx_pos<priv->idx_size){
- int64_t pos;
-
- idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++];
-
- if(idx->dwFlags&AVIIF_LIST){
- if (!valid_stream_id(idx->ckid))
- // LIST
- continue;
- if (!priv->warned_unaligned)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Looks like unaligned chunk in index, broken AVI file!\n");
- priv->warned_unaligned = 1;
- }
- if(!demux_avi_select_stream(demux,idx->ckid)){
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid);
- continue; // skip this chunk
- }
-
- pos = (int64_t)priv->idx_offset+AVI_IDX_OFFSET(idx);
- if((pos<demux->movi_start || pos>=demux->movi_end) && (demux->movi_end>demux->movi_start) && (demux->stream->flags & MP_STREAM_SEEK)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! idx=0x%"PRIX64" \n",(int64_t)pos);
- continue;
- }
- stream_seek(demux->stream,pos);
- demux->filepos=stream_tell(demux->stream);
- id=stream_read_dword_le(demux->stream);
- if(stream_eof(demux->stream)) return 0; // EOF!
-
- if(id!=idx->ckid){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s \n",(char *)&id,(char *)&idx->ckid);
- if(valid_fourcc(idx->ckid))
- id=idx->ckid; // use index if valid
- else
- if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad
- }
- len=stream_read_dword_le(demux->stream);
- if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%d \n",len,idx->dwChunkLength);
- if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :(
- len=choose_chunk_len(idx->dwChunkLength,len);
- }
- if(!(idx->dwFlags&AVIIF_KEYFRAME)) flags=0;
- } else {
- demux->filepos=stream_tell(demux->stream);
- if(demux->filepos>=demux->movi_end && demux->movi_end>demux->movi_start && (demux->stream->flags & MP_STREAM_SEEK)){
- demux->stream->eof=1;
- return 0;
- }
- id=avi_find_id(demux->stream);
- len=stream_read_dword_le(demux->stream);
- if(stream_eof(demux->stream)) return 0; // EOF!
-
- if(id==mmioFOURCC('L','I','S','T') || id==mmioFOURCC('R', 'I', 'F', 'F')){
- id=stream_read_dword_le(demux->stream); // list or RIFF type
- continue;
- }
- }
-
- ds=demux_avi_select_stream(demux,id);
- if(ds)
- if(ds->packs+1>=MAX_PACKS || ds->bytes+len>=MAX_PACK_BYTES){
- // this packet will cause a buffer overflow, switch to -ni mode!!!
- mp_tmsg(MSGT_DEMUX,MSGL_WARN,"\nBadly interleaved AVI file detected - switching to --avi-ni mode...\n");
- if(priv->idx_size>0){
- // has index
- demux->type=DEMUXER_TYPE_AVI_NI;
- demux->desc=&demuxer_desc_avi_ni;
- --priv->idx_pos; // hack
- } else {
- // no index
- demux->type=DEMUXER_TYPE_AVI_NINI;
- demux->desc=&demuxer_desc_avi_nini;
- priv->idx_pos=demux->filepos; // hack
- }
- priv->idx_pos_v=priv->idx_pos_a=priv->idx_pos;
- // quit now, we can't even (no enough buffer memory) read this packet :(
- return -1;
- }
-
- ret=demux_avi_read_packet(demux,ds,id,len,priv->idx_pos-1,flags);
-} while(ret!=1);
- return 1;
-}
-
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_avi_fill_buffer_ni(demuxer_t *demux, demux_stream_t *ds)
-{
-avi_priv_t *priv=demux->priv;
-unsigned int id=0;
-unsigned int len;
-int ret=0;
-
-do{
- int flags=1;
- AVIINDEXENTRY *idx=NULL;
- int idx_pos=0;
- demux->filepos=stream_tell(demux->stream);
-
- if(ds==demux->video) idx_pos=priv->idx_pos_v++; else
- if(ds==demux->audio) idx_pos=priv->idx_pos_a++; else
- idx_pos=priv->idx_pos++;
-
- if(priv->idx_size>0 && idx_pos<priv->idx_size){
- int64_t pos;
- idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos];
-
- if(idx->dwFlags&AVIIF_LIST){
- if (!valid_stream_id(idx->ckid))
- // LIST
- continue;
- if (!priv->warned_unaligned)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Looks like unaligned chunk in index, broken AVI file!\n");
- priv->warned_unaligned = 1;
- }
- if(ds && demux_avi_select_stream(demux,idx->ckid)!=ds){
- mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid);
- continue; // skip this chunk
- }
-
- pos = priv->idx_offset+AVI_IDX_OFFSET(idx);
- if((pos<demux->movi_start || pos>=demux->movi_end) && (demux->movi_end>demux->movi_start)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! current=0x%"PRIX64" idx=0x%"PRIX64" \n",(int64_t)demux->filepos,(int64_t)pos);
- continue;
- }
- stream_seek(demux->stream,pos);
-
- id=stream_read_dword_le(demux->stream);
-
- if(stream_eof(demux->stream)) return 0;
-
- if(id!=idx->ckid){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s \n",(char *)&id,(char *)&idx->ckid);
- if(valid_fourcc(idx->ckid))
- id=idx->ckid; // use index if valid
- else
- if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad
- }
- len=stream_read_dword_le(demux->stream);
- if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%d \n",len,idx->dwChunkLength);
- if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :(
- len=choose_chunk_len(idx->dwChunkLength,len);
- }
- if(!(idx->dwFlags&AVIIF_KEYFRAME)) flags=0;
- } else return 0;
- ret=demux_avi_read_packet(demux,demux_avi_select_stream(demux,id),id,len,idx_pos,flags);
-} while(ret!=1);
- return 1;
-}
-
-
-// return value:
-// 0 = EOF or no stream found
-// 1 = successfully read a packet
-static int demux_avi_fill_buffer_nini(demuxer_t *demux, demux_stream_t *ds)
-{
-avi_priv_t *priv=demux->priv;
-unsigned int id=0;
-unsigned int len;
-int ret=0;
-int64_t *fpos=NULL;
-
- if(ds==demux->video) fpos=&priv->idx_pos_v; else
- if(ds==demux->audio) fpos=&priv->idx_pos_a; else
- return 0;
-
- stream_seek(demux->stream,fpos[0]);
-
-do{
-
- demux->filepos=stream_tell(demux->stream);
- if(demux->filepos>=demux->movi_end && (demux->movi_end>demux->movi_start)){
- ds->eof=1;
- return 0;
- }
-
- id=avi_find_id(demux->stream);
- len=stream_read_dword_le(demux->stream);
-
- if(stream_eof(demux->stream)) return 0;
-
- if(id==mmioFOURCC('L','I','S','T')){
- id=stream_read_dword_le(demux->stream); // list type
- continue;
- }
-
- if(id==mmioFOURCC('R','I','F','F')){
- mp_msg(MSGT_DEMUX,MSGL_V,"additional RIFF header...\n");
- id=stream_read_dword_le(demux->stream); // "AVIX"
- continue;
- }
-
- if(ds==demux_avi_select_stream(demux,id)){
- // read it!
- ret=demux_avi_read_packet(demux,ds,id,len,priv->idx_pos-1,0);
- } else {
- // skip it!
- int skip=(len+1)&(~1); // total bytes in this chunk
- stream_skip(demux->stream,skip);
- }
-
-} while(ret!=1);
- fpos[0]=stream_tell(demux->stream);
- return 1;
-}
-
-// AVI demuxer parameters:
-int index_mode=-1; // -1=untouched 0=don't use index 1=use (generate) index
-int force_ni=0; // force non-interleaved AVI parsing
-
-static demuxer_t* demux_open_avi(demuxer_t* demuxer){
- demux_stream_t *d_audio=demuxer->audio;
- demux_stream_t *d_video=demuxer->video;
- sh_audio_t *sh_audio=NULL;
- sh_video_t *sh_video=NULL;
- avi_priv_t* priv=calloc(1, sizeof(avi_priv_t));
-
- demuxer->priv=(void*)priv;
-
- //---- AVI header:
- read_avi_header(demuxer,(demuxer->stream->flags & MP_STREAM_SEEK_BW)?index_mode:-2);
- update_audio_block_size(demuxer);
-
- if(demuxer->audio->id>=0 && !demuxer->a_streams[demuxer->audio->id]){
- mp_tmsg(MSGT_DEMUX,MSGL_WARN,"AVI: invalid audio stream ID: %d - ignoring (nosound)\n",demuxer->audio->id);
- demuxer->audio->id=-2; // disabled
- }
- if(demuxer->video->id>=0 && !demuxer->v_streams[demuxer->video->id]){
- mp_tmsg(MSGT_DEMUX,MSGL_WARN,"AVI: invalid video stream ID: %d - ignoring (using default)\n",demuxer->video->id);
- demuxer->video->id=-1; // autodetect
- }
-
- stream_seek(demuxer->stream,demuxer->movi_start);
- if(priv->idx_size>1){
- // decide index format:
-#if 1
- if((AVI_IDX_OFFSET(&((AVIINDEXENTRY *)priv->idx)[0])<demuxer->movi_start ||
- AVI_IDX_OFFSET(&((AVIINDEXENTRY *)priv->idx)[1])<demuxer->movi_start )&& !priv->isodml)
- priv->idx_offset=demuxer->movi_start-4;
-#else
- if(AVI_IDX_OFFSET(&((AVIINDEXENTRY *)priv->idx)[0])<demuxer->movi_start)
- priv->idx_offset=demuxer->movi_start-4;
-#endif
- mp_msg(MSGT_DEMUX,MSGL_V,"AVI index offset: 0x%X (movi=0x%X idx0=0x%X idx1=0x%X)\n",
- (int)priv->idx_offset,(int)demuxer->movi_start,
- (int)((AVIINDEXENTRY *)priv->idx)[0].dwChunkOffset,
- (int)((AVIINDEXENTRY *)priv->idx)[1].dwChunkOffset);
- }
-
- if(priv->idx_size>0){
- // check that file is non-interleaved:
- int i;
- int64_t a_pos=-1;
- int64_t v_pos=-1;
- for(i=0;i<priv->idx_size;i++){
- AVIINDEXENTRY* idx=&((AVIINDEXENTRY *)priv->idx)[i];
- demux_stream_t* ds=demux_avi_select_stream(demuxer,idx->ckid);
- int64_t pos = priv->idx_offset + AVI_IDX_OFFSET(idx);
- if(a_pos==-1 && ds==demuxer->audio){
- a_pos=pos;
- if(v_pos!=-1) break;
- }
- if(v_pos==-1 && ds==demuxer->video){
- v_pos=pos;
- if(a_pos!=-1) break;
- }
- }
- if(v_pos==-1){
- mp_msg(MSGT_DEMUX, MSGL_ERR, "AVI_NI: %s",
- mp_gtext("No video stream found.\n"));
- return NULL;
- }
- if(a_pos==-1){
- d_audio->sh=sh_audio=NULL;
- } else {
- if(force_ni || abs(a_pos-v_pos)>0x100000){ // distance > 1MB
- mp_tmsg(MSGT_DEMUX,MSGL_INFO,"%s NON-INTERLEAVED AVI file format.\n",force_ni?"Forced":"Detected");
- demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!!
- demuxer->desc=&demuxer_desc_avi_ni; // HACK!!!!
- pts_from_bps=1; // force BPS sync!
- }
- }
- } else {
- // no index
- if(force_ni){
- mp_tmsg(MSGT_DEMUX,MSGL_INFO,"Using NON-INTERLEAVED broken AVI file format.\n");
- demuxer->type=DEMUXER_TYPE_AVI_NINI; // HACK!!!!
- demuxer->desc=&demuxer_desc_avi_nini; // HACK!!!!
- priv->idx_pos_a=
- priv->idx_pos_v=demuxer->movi_start;
- pts_from_bps=1; // force BPS sync!
- }
- demuxer->seekable=0;
- }
- if(!ds_fill_buffer(d_video)){
- mp_msg(MSGT_DEMUX, MSGL_ERR, "AVI: %s",
- mp_gtext("Missing video stream!? Contact the author, "
- "it may be a bug :(\n"));
- return NULL;
- }
- sh_video=d_video->sh;sh_video->ds=d_video;
- if(d_audio->id!=-2){
- mp_msg(MSGT_DEMUX,MSGL_V,"AVI: Searching for audio stream (id:%d)\n",d_audio->id);
- if(!priv->audio_streams || !ds_fill_buffer(d_audio)){
- mp_msg(MSGT_DEMUX, MSGL_INFO, "AVI: %s",
- mp_gtext("No audio stream found -> no sound.\n"));
- d_audio->sh=sh_audio=NULL;
- } else {
- sh_audio=d_audio->sh;sh_audio->ds=d_audio;
- }
- }
-
- // calculating audio/video bitrate:
- if(priv->idx_size>0){
- // we have index, let's count 'em!
- AVIINDEXENTRY *idx = priv->idx;
- int64_t vsize=0;
- int64_t asize=0;
- size_t vsamples=0;
- size_t asamples=0;
- int i;
- for(i=0;i<priv->idx_size;i++){
- int id=avi_stream_id(idx[i].ckid);
- unsigned len=idx[i].dwChunkLength;
- if(sh_video->ds->id == id) {
- vsize+=len;
- ++vsamples;
- }
- else if(sh_audio && sh_audio->ds->id == id) {
- asize+=len;
- asamples+=(len+priv->audio_block_size-1)/priv->audio_block_size;
- }
- }
- mp_msg(MSGT_DEMUX, MSGL_V,
- "AVI video size=%"PRId64" (%zu) audio size=%"PRId64" (%zu)\n",
- vsize, vsamples, asize, asamples);
- priv->numberofframes=vsamples;
- sh_video->i_bps=((float)vsize/(float)vsamples)*(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
- if(sh_audio) sh_audio->i_bps=((float)asize/(float)asamples)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
- } else {
- // guessing, results may be inaccurate:
- int64_t vsize;
- int64_t asize=0;
-
- if((priv->numberofframes=sh_video->video.dwLength)<=1)
- // bad video header, try to get number of frames from audio
- if(sh_audio && sh_audio->wf->nAvgBytesPerSec) priv->numberofframes=sh_video->fps*sh_audio->audio.dwLength/sh_audio->audio.dwRate*sh_audio->audio.dwScale;
- if(priv->numberofframes<=1){
- mp_tmsg(MSGT_SEEK,MSGL_WARN,"Could not determine number of frames (for absolute seek).\n");
- priv->numberofframes=0;
- }
-
- if(sh_audio){
- if(sh_audio->wf->nAvgBytesPerSec && sh_audio->audio.dwSampleSize!=1){
- asize=(float)sh_audio->wf->nAvgBytesPerSec*sh_audio->audio.dwLength*sh_audio->audio.dwScale/sh_audio->audio.dwRate;
- } else {
- asize=sh_audio->audio.dwLength;
- sh_audio->i_bps=(float)asize/(sh_video->frametime*priv->numberofframes);
- }
- }
- vsize=demuxer->movi_end-demuxer->movi_start-asize-8*priv->numberofframes;
- mp_msg(MSGT_DEMUX,MSGL_V,"AVI video size=%"PRId64" (%u) audio size=%"PRId64"\n",vsize,priv->numberofframes,asize);
- sh_video->i_bps=(float)vsize/(sh_video->frametime*priv->numberofframes);
- }
-
- return demuxer;
-
-}
-
-
-static void demux_seek_avi(demuxer_t *demuxer, float rel_seek_secs,
- float audio_delay, int flags)
-{
- avi_priv_t *priv=demuxer->priv;
- 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;
- float skip_audio_secs=0;
-
- //FIXME: OFF_T - Didn't check AVI case yet (avi files can't be >2G anyway?)
- //================= seek in AVI ==========================
- int rel_seek_frames=rel_seek_secs*sh_video->fps;
- int video_chunk_pos=d_video->pos;
- int i;
-
- if(flags&SEEK_ABSOLUTE){
- // seek absolute
- video_chunk_pos=0;
- }
-
- if(flags&SEEK_FACTOR){
- rel_seek_frames=rel_seek_secs*priv->numberofframes;
- }
-
- priv->skip_video_frames=0;
- priv->avi_audio_pts=0;
-
-// ------------ STEP 1: find nearest video keyframe chunk ------------
- // find nearest video keyframe chunk pos:
- if(rel_seek_frames>0){
- // seek forward
- while(video_chunk_pos<priv->idx_size-1){
- int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
- if(avi_stream_id(id)==d_video->id){ // video frame
- if((--rel_seek_frames)<0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
- }
- ++video_chunk_pos;
- }
- } else {
- // seek backward
- while(video_chunk_pos>0){
- int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
- if(avi_stream_id(id)==d_video->id){ // video frame
- if((++rel_seek_frames)>0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
- }
- --video_chunk_pos;
- }
- }
- priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=video_chunk_pos;
-
- // re-calc video pts:
- d_video->pack_no=0;
- for(i=0;i<video_chunk_pos;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
- if(avi_stream_id(id)==d_video->id) ++d_video->pack_no;
- }
- priv->video_pack_no=d_video->pack_no;
- priv->avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
- d_video->pos=video_chunk_pos;
-
- mp_msg(MSGT_SEEK,MSGL_DBG2,"V_SEEK: pack=%d pts=%5.3f chunk=%d \n",d_video->pack_no,priv->avi_video_pts,video_chunk_pos);
-
-// ------------ STEP 2: seek audio, find the right chunk & pos ------------
-
- d_audio->pack_no=0;
- priv->audio_block_no=0;
- d_audio->dpos=0;
-
- if(sh_audio){
- int i;
- int len=0;
- int skip_audio_bytes=0;
- int curr_audio_pos=-1;
- int audio_chunk_pos=-1;
- int chunk_max=(demuxer->type==DEMUXER_TYPE_AVI)?video_chunk_pos:priv->idx_size;
-
- if(sh_audio->audio.dwSampleSize){
- // constant rate audio stream
- /* immediate seeking to audio position, including when streams are delayed */
- curr_audio_pos=(priv->avi_video_pts + audio_delay)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
- curr_audio_pos*=sh_audio->audio.dwSampleSize;
-
- // find audio chunk pos:
- for(i=0;i<chunk_max;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
- if(avi_stream_id(id)==d_audio->id){
- len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
- if(d_audio->dpos<=curr_audio_pos && curr_audio_pos<(d_audio->dpos+len)){
- break;
- }
- ++d_audio->pack_no;
- priv->audio_block_no+=
- (len+priv->audio_block_size-1)/priv->audio_block_size;
- d_audio->dpos+=len;
- }
- }
- audio_chunk_pos=i;
- skip_audio_bytes=curr_audio_pos-d_audio->dpos;
-
- mp_msg(MSGT_SEEK,MSGL_V,"SEEK: i=%d (max:%d) dpos=%d (wanted:%d) \n",
- i,chunk_max,(int)d_audio->dpos,curr_audio_pos);
-
- } else {
- // VBR audio
- /* immediate seeking to audio position, including when streams are delayed */
- int chunks=(priv->avi_video_pts + audio_delay)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
- audio_chunk_pos=0;
-
- // find audio chunk pos:
- for(i=0;i<priv->idx_size && chunks>0;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
- if(avi_stream_id(id)==d_audio->id){
- len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
- if(i>chunk_max){
- skip_audio_bytes+=len;
- } else {
- ++d_audio->pack_no;
- priv->audio_block_no+=
- (len+priv->audio_block_size-1)/priv->audio_block_size;
- d_audio->dpos+=len;
- audio_chunk_pos=i;
- }
- chunks-=(len+priv->audio_block_size-1)/priv->audio_block_size;
- }
- }
- }
-
- // Now we have:
- // audio_chunk_pos = chunk no in index table (it's <=chunk_max)
- // skip_audio_bytes = bytes to be skipped after chunk seek
- // d-audio->pack_no = chunk_no in stream at audio_chunk_pos
- // d_audio->dpos = bytepos in stream at audio_chunk_pos
- // let's seek!
-
- // update stream position:
- d_audio->pos=audio_chunk_pos;
-
- if(demuxer->type==DEMUXER_TYPE_AVI){
- // interleaved stream:
- if(audio_chunk_pos<video_chunk_pos){
- // calc priv->skip_video_frames & adjust video pts counter:
- for(i=audio_chunk_pos;i<video_chunk_pos;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
- if(avi_stream_id(id)==d_video->id) ++priv->skip_video_frames;
- }
- // requires for correct audio pts calculation (demuxer):
- priv->avi_video_pts-=priv->skip_video_frames*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
- priv->avi_audio_pts=priv->avi_video_pts;
- // set index position:
- priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=audio_chunk_pos;
- }
- } else {
- // non-interleaved stream:
- priv->idx_pos_a=audio_chunk_pos;
- priv->idx_pos_v=video_chunk_pos;
- priv->idx_pos=(audio_chunk_pos<video_chunk_pos)?audio_chunk_pos:video_chunk_pos;
- }
-
- mp_msg(MSGT_SEEK,MSGL_V,"SEEK: idx=%d (a:%d v:%d) v.skip=%d a.skip=%d/%4.3f \n",
- (int)priv->idx_pos,audio_chunk_pos,video_chunk_pos,
- (int)priv->skip_video_frames,skip_audio_bytes,skip_audio_secs);
-
- if(skip_audio_bytes){
- demux_read_data(d_audio,NULL,skip_audio_bytes);
- }
-
- }
- d_video->pts=priv->avi_video_pts; // OSD
-
-}
-
-
-static void demux_close_avi(demuxer_t *demuxer)
-{
- avi_priv_t* priv=demuxer->priv;
-
- if(!priv)
- return;
-
- if(priv->idx_size > 0)
- free(priv->idx);
- free(priv);
-}
-
-
-static int demux_avi_control(demuxer_t *demuxer,int cmd, void *arg){
- avi_priv_t *priv=demuxer->priv;
- demux_stream_t *d_video=demuxer->video;
- sh_video_t *sh_video=d_video->sh;
-
- switch(cmd) {
- case DEMUXER_CTRL_GET_TIME_LENGTH:
- if (!priv->numberofframes || !sh_video) return DEMUXER_CTRL_DONTKNOW;
- *((double *)arg)=(double)priv->numberofframes/sh_video->fps;
- if (sh_video->video.dwLength<=1) return DEMUXER_CTRL_GUESS;
- return DEMUXER_CTRL_OK;
-
- case DEMUXER_CTRL_SWITCH_AUDIO:
- case DEMUXER_CTRL_SWITCH_VIDEO: {
- int audio = (cmd == DEMUXER_CTRL_SWITCH_AUDIO);
- demux_stream_t *ds = audio ? demuxer->audio : demuxer->video;
- void **streams = audio ? (void **)demuxer->a_streams : (void **)demuxer->v_streams;
- int maxid = FFMIN(100, audio ? MAX_A_STREAMS : MAX_V_STREAMS);
- int chunkid;
- if (ds->id < -1)
- ds->id = -1;
-
- if (*(int *)arg >= 0)
- ds->id = *(int *)arg;
- else {
- int i;
- for (i = 0; i < maxid; i++) {
- if (++ds->id >= maxid) ds->id = 0;
- if (streams[ds->id]) break;
- }
- }
-
- chunkid = (ds->id / 10 + '0') | (ds->id % 10 + '0') << 8;
- ds->sh = NULL;
- if (!streams[ds->id]) // stream not available
- ds->id = -1;
- else
- demux_avi_select_stream(demuxer, chunkid);
- *(int *)arg = ds->id;
- return DEMUXER_CTRL_OK;
- }
-
- default:
- return DEMUXER_CTRL_NOTIMPL;
- }
-}
-
-
-static int avi_check_file(demuxer_t *demuxer)
-{
- int id=stream_read_dword_le(demuxer->stream); // "RIFF"
-
- if((id==mmioFOURCC('R','I','F','F')) || (id==mmioFOURCC('O','N','2',' '))) {
- stream_read_dword_le(demuxer->stream); //filesize
- id=stream_read_dword_le(demuxer->stream); // "AVI "
- if(id==formtypeAVI)
- return DEMUXER_TYPE_AVI;
- // "Samsung Digimax i6 PMP" crap according to bug 742
- if(id==mmioFOURCC('A','V','I',0x19))
- return DEMUXER_TYPE_AVI;
- if(id==mmioFOURCC('O','N','2','f')){
- mp_tmsg(MSGT_DEMUXER,MSGL_INFO,"ON2 AVI format");
- return DEMUXER_TYPE_AVI;
- }
- }
-
- return 0;
-}
-
-
-const demuxer_desc_t demuxer_desc_avi = {
- "AVI demuxer",
- "avi",
- "AVI",
- "Arpi?",
- "AVI files, including non interleaved files",
- DEMUXER_TYPE_AVI,
- 1, // safe autodetect
- avi_check_file,
- demux_avi_fill_buffer,
- demux_open_avi,
- demux_close_avi,
- demux_seek_avi,
- demux_avi_control
-};
-
-const demuxer_desc_t demuxer_desc_avi_ni = {
- "AVI demuxer, non-interleaved",
- "avini",
- "AVI",
- "Arpi?",
- "AVI files, including non interleaved files",
- DEMUXER_TYPE_AVI,
- 1, // safe autodetect
- avi_check_file,
- demux_avi_fill_buffer_ni,
- demux_open_avi,
- demux_close_avi,
- demux_seek_avi,
- demux_avi_control
-};
-
-const demuxer_desc_t demuxer_desc_avi_nini = {
- "AVI demuxer, non-interleaved and no index",
- "avinini",
- "AVI",
- "Arpi?",
- "AVI files, including non interleaved files",
- DEMUXER_TYPE_AVI,
- 1, // safe autodetect
- avi_check_file,
- demux_avi_fill_buffer_nini,
- demux_open_avi,
- demux_close_avi,
- demux_seek_avi,
- demux_avi_control
-};
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 39e1cb28c5..466ab7537b 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -510,7 +510,7 @@ static demuxer_t *demux_open_lavf(demuxer_t *demuxer)
if (opts->user_correct_pts != 0)
avfc->flags |= AVFMT_FLAG_GENPTS;
}
- if (index_mode == 0)
+ if (opts->index_mode == 0)
avfc->flags |= AVFMT_FLAG_IGNIDX;
if (lavfdopts->probesize) {
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 1c93fa588c..724bf6255b 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -722,10 +722,11 @@ static void add_block_position(demuxer_t *demuxer, struct mkv_track *track,
static int demux_mkv_read_cues(demuxer_t *demuxer)
{
+ struct MPOpts *opts = demuxer->opts;
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
stream_t *s = demuxer->stream;
- if (index_mode == 0 || index_mode == 2) {
+ if (opts->index_mode == 0 || opts->index_mode == 2) {
ebml_read_skip(s, NULL);
return 0;
}
diff --git a/demux/demux_mpg.c b/demux/demux_mpg.c
deleted file mode 100644
index d47b3afd86..0000000000
--- a/demux/demux_mpg.c
+++ /dev/null
@@ -1,1306 +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 "core/mp_msg.h"
-#include "core/options.h"
-
-#include "libavutil/attributes.h"
-#include "audio/decode/dec_audio.h"
-#include "stream/stream.h"
-#include "demux.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;
-int64_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, int64_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
- int64_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;
- mp_set_audio_codec_from_tag(sh_a);
- }
- if(demux->audio->id==-1) demux->audio->id=aid;
-}
-
-static void dvdpcm_header(sh_audio_t *sh)
-{
- if (sh->format != 0x10001)
- return;
-
- WAVEFORMATEX *wf = calloc(sizeof(*wf), 1);
-
- if(sh->codecdata_len==3){
- // we have LPCM header:
- unsigned char h=sh->codecdata[1];
- wf->nChannels=1+(h&7);
- switch((h>>4)&3){
- case 0: wf->nSamplesPerSec=48000;break;
- case 1: wf->nSamplesPerSec=96000;break;
- case 2: wf->nSamplesPerSec=44100;break;
- case 3: wf->nSamplesPerSec=32000;break;
- }
- switch ((h >> 6) & 3) {
- case 0:
- wf->wBitsPerSample = 2 * 8;
- break;
- case 1:
- mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, "Samples of this format are needed to improve support. Please contact the developers.\n");
- wf->nAvgBytesPerSec = wf->nChannels * wf->nSamplesPerSec * 5 / 2;
- case 2:
- wf->wBitsPerSample = 3 * 8;
- break;
- default:
- wf->wBitsPerSample = 2 * 8;
- }
- } else {
- // use defaults:
- wf->nChannels=2;
- wf->nSamplesPerSec=48000;
- wf->wBitsPerSample = 2 * 8;
- }
- if (!wf->nAvgBytesPerSec)
- wf->nAvgBytesPerSec = wf->wBitsPerSample / 8 * wf->nChannels * wf->nSamplesPerSec;
- if (wf->wBitsPerSample == 16)
- sh->format = 0x20776172; // 'raw ', pcm_s16be
- sh->wf = wf;
-}
-
-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');
- mp_set_video_codec_from_tag(sh);
- }
- }
- }
- //============== DVD Audio sub-stream ======================
- if(id==0x1BD){
- int aid, rawa52 = 0;
- int64_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->gsh->codec = "dvd_subtitle_mpg";
- 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");
- dvdpcm_header((sh_audio_t*)(ds->sh));
- mp_set_audio_codec_from_tag((sh_audio_t*)(ds->sh));
- }
-// 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]);
- dvdpcm_header(sh);
- mp_set_audio_codec_from_tag(sh);
- }
- }
- } 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_set_video_codec_from_tag(sh);
- 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;
- int64_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)(uintptr_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 *)(uintptr_t)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;
- int64_t oldpos = demuxer->filepos;
- float newpts = 0;
- int64_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_START_TIME:
- if (mpg_d && mpg_d->has_valid_timestamps && mpg_d->first_to_final_pts_len > 0.0) {
- *((float *)arg)=mpg_d->first_pts;
- 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;
-
- demuxer->ts_resets_possible = true;
-
- 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;
-
- demuxer->ts_resets_possible = true;
-
- 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;
-
- demuxer->ts_resets_possible = true;
-
- 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;
- int64_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;
- mp_set_video_codec_from_tag(sh_video);
- }
-
- 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/demux/demux_ts.c b/demux/demux_ts.c
deleted file mode 100644
index a16891907d..0000000000
--- a/demux/demux_ts.c
+++ /dev/null
@@ -1,3532 +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 "core/mp_msg.h"
-#include "core/options.h"
-
-#include "audio/decode/dec_audio.h"
-#include "stream/stream.h"
-#include "demux.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;
-int64_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'),
- AUDIO_PCM_BR = mmioFOURCC('B', 'P', 'C', 'M'),
- 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_PCM_BR:
- 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 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;
- mp_set_audio_codec_from_tag(sh);
- 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;
- mp_set_video_codec_from_tag(sh);
- 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->gsh->codec = "dvb_subtitle"; break;
- case SPU_DVD:
- sh->gsh->codec = "dvd_subtitle"; break;
- case SPU_PGS:
- sh->gsh->codec = "hdmv_pgs_subtitle"; 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;
- int64_t pos = 0;
- int64_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");
- 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 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 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 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 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;
- int64_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 int64_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;
- int64_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_PCM_BR)
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO PCMBR(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;
- int64_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;
- demuxer->ts_resets_possible = true;
-
- 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;
-
- 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;
- mp_set_video_codec_from_tag(sh_video);
- 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;
- mp_set_audio_codec_from_tag(sh_audio);
- 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_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 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 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;
- 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)
- {
- priv->pat.progs = realloc_struct(priv->pat.progs, priv->pat.progs_cnt+1, sizeof(struct pat_progs_t));
- if(!priv->pat.progs)
- {
- int sz = sizeof(struct pat_progs_t) * (priv->pat.progs_cnt+1);
- priv->pat.progs_cnt = 0;
- mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PAT: COULDN'T REALLOC %d bytes, NEXT\n", sz);
- break;
- }
- 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 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;
-
- 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)
- {
- pmt->mp4es = realloc_struct(pmt->mp4es, pmt->mp4es_cnt+1, sizeof(mp4_es_descr_t));
- if(!pmt->mp4es)
- {
- pmt->mp4es_cnt = 0;
- fprintf(stderr, "CAN'T REALLOC MP4_ES_DESCR\n");
- continue;
- }
- 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+j+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;
- ts_section_t *section;
- ES_stream_t *tss;
- int i;
-
- idx = progid_idx_in_pmt(priv, progid);
-
- if(idx == -1)
- {
- priv->pmt = realloc_struct(priv->pmt, priv->pmt_cnt + 1, sizeof(pmt_t));
- if(!priv->pmt)
- {
- int sz = (priv->pmt_cnt + 1) * sizeof(pmt_t);
- priv->pmt_cnt = 0;
- mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT: COULDN'T REALLOC %d bytes, NEXT\n", sz);
- return 0;
- }
- 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)
- {
- pmt->es = realloc_struct(pmt->es, pmt->es_cnt + 1, sizeof(struct pmt_es_t));
- if(!pmt->es)
- {
- int sz = sizeof(struct pmt_es_t) * (pmt->es_cnt + 1);
- pmt->es_cnt = 0;
- mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT, COULDN'T ALLOCATE %d bytes for PMT_ES\n", sz);
- continue;
- }
- 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 0x80:
- pmt->es[idx].type = AUDIO_PCM_BR;
- 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 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 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->gsh->demuxer_id == 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;
- int64_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/demux/demux_ts.h b/demux/demux_ts.h
deleted file mode 100644
index 37bddb86da..0000000000
--- a/demux/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/demux/extension.c b/demux/extension.c
index 71b5bf8f4d..30cb592b9f 100644
--- a/demux/extension.c
+++ b/demux/extension.c
@@ -38,17 +38,17 @@ static struct {
const char *extension;
int demuxer_type;
} extensions_table[] = {
- { "vob", DEMUXER_TYPE_MPEG_PS },
- { "m2v", DEMUXER_TYPE_MPEG_PS },
- { "avi", DEMUXER_TYPE_AVI },
- { "asx", DEMUXER_TYPE_ASF },
- { "asf", DEMUXER_TYPE_ASF },
- { "wmv", DEMUXER_TYPE_ASF },
- { "wma", DEMUXER_TYPE_ASF },
+ { "vob", DEMUXER_TYPE_LAVF },
+ { "m2v", DEMUXER_TYPE_LAVF },
+ { "avi", DEMUXER_TYPE_LAVF },
+ { "asx", DEMUXER_TYPE_LAVF },
+ { "asf", DEMUXER_TYPE_LAVF },
+ { "wmv", DEMUXER_TYPE_LAVF },
+ { "wma", DEMUXER_TYPE_LAVF },
{ "rm", DEMUXER_TYPE_LAVF },
{ "rmvb", DEMUXER_TYPE_LAVF },
{ "ra", DEMUXER_TYPE_LAVF },
- { "y4m", DEMUXER_TYPE_Y4M },
+ { "y4m", DEMUXER_TYPE_LAVF },
{ "mp3", DEMUXER_TYPE_LAVF },
{ "wav", DEMUXER_TYPE_LAVF },
{ "flac", DEMUXER_TYPE_LAVF },
@@ -63,12 +63,9 @@ static struct {
{ "it", DEMUXER_TYPE_LAVF },
{ "mid", DEMUXER_TYPE_LAVF },
{ "midi", DEMUXER_TYPE_LAVF },
- { "nsv", DEMUXER_TYPE_NSV },
- { "nsa", DEMUXER_TYPE_NSV },
- { "mpc", DEMUXER_TYPE_MPC },
-#ifdef CONFIG_WIN32DLL
- { "avs", DEMUXER_TYPE_AVS },
-#endif
+ { "nsv", DEMUXER_TYPE_LAVF },
+ { "nsa", DEMUXER_TYPE_LAVF },
+ { "mpc", DEMUXER_TYPE_LAVF },
{ "302", DEMUXER_TYPE_LAVF },
{ "264", DEMUXER_TYPE_LAVF },
{ "26l", DEMUXER_TYPE_LAVF },
diff --git a/demux/mp3_hdr.c b/demux/mp3_hdr.c
deleted file mode 100644
index 27a02368da..0000000000
--- a/demux/mp3_hdr.c
+++ /dev/null
@@ -1,144 +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 "config.h"
-#include "mp3_hdr.h"
-#include "core/mp_msg.h"
-
-//----------------------- mp3 audio frame header parser -----------------------
-
-static int tabsel_123[2][3][16] = {
- { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
- {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0},
- {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0} },
-
- { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
- {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
- {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0} }
-};
-
-static long freqs[9] = { 44100, 48000, 32000, // MPEG 1.0
- 22050, 24000, 16000, // MPEG 2.0
- 11025, 12000, 8000}; // MPEG 2.5
-
-/*
- * return frame size or -1 (bad frame)
- */
-int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* srate, int* spf, int* mpa_layer, int* br){
- int stereo,ssize,lsf,framesize,padding,bitrate_index,sampling_frequency, divisor;
- int bitrate;
- int layer, mult[3] = { 12000, 144000, 144000 };
- unsigned long newhead =
- hbuf[0] << 24 |
- hbuf[1] << 16 |
- hbuf[2] << 8 |
- hbuf[3];
-
-// printf("head=0x%08X\n",newhead);
-
- // head_check:
- if( (newhead & 0xffe00000) != 0xffe00000 ){
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"head_check failed\n");
- return -1;
- }
-
- layer = 4-((newhead>>17)&3);
- if(layer==4){
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"not layer-1/2/3\n");
- return -1;
- }
-
- sampling_frequency = ((newhead>>10)&0x3); // valid: 0..2
- if(sampling_frequency==3){
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"invalid sampling_frequency\n");
- return -1;
- }
-
- if( newhead & ((long)1<<20) ) {
- // MPEG 1.0 (lsf==0) or MPEG 2.0 (lsf==1)
- lsf = (newhead & ((long)1<<19)) ? 0x0 : 0x1;
- sampling_frequency += (lsf*3);
- } else {
- // MPEG 2.5
- lsf = 1;
- sampling_frequency += 6;
- }
-
-// crc = ((newhead>>16)&0x1)^0x1;
- bitrate_index = ((newhead>>12)&0xf); // valid: 1..14
- padding = ((newhead>>9)&0x1);
-// fr->extension = ((newhead>>8)&0x1);
-// fr->mode = ((newhead>>6)&0x3);
-// fr->mode_ext = ((newhead>>4)&0x3);
-// fr->copyright = ((newhead>>3)&0x1);
-// fr->original = ((newhead>>2)&0x1);
-// fr->emphasis = newhead & 0x3;
-
- stereo = ( (((newhead>>6)&0x3)) == 3) ? 1 : 2;
-
-// !checked later through tabsel_123[]!
-// if(!bitrate_index || bitrate_index==15){
-// mp_msg(MSGT_DEMUXER,MSGL_DBG2,"Free format not supported.\n");
-// return -1;
-// }
-
- if(lsf)
- ssize = (stereo == 1) ? 9 : 17;
- else
- ssize = (stereo == 1) ? 17 : 32;
- if(!((newhead>>16)&0x1)) ssize += 2; // CRC
-
- bitrate = tabsel_123[lsf][layer-1][bitrate_index];
- framesize = bitrate * mult[layer-1];
-
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"FRAMESIZE: %d, layer: %d, bitrate: %d, mult: %d\n",
- framesize, layer, tabsel_123[lsf][layer-1][bitrate_index], mult[layer-1]);
- if(!framesize){
- mp_msg(MSGT_DEMUXER,MSGL_DBG2,"invalid framesize/bitrate_index\n");
- return -1;
- }
-
- divisor = (layer == 3 ? (freqs[sampling_frequency] << lsf) : freqs[sampling_frequency]);
- framesize /= divisor;
- if(layer==1)
- framesize = (framesize+padding)*4;
- else
- framesize += padding;
-
-// if(framesize<=0 || framesize>MAXFRAMESIZE) return FALSE;
- if(srate) {
- *srate = freqs[sampling_frequency];
- if(spf) {
- if(layer == 1)
- *spf = 384;
- else if(layer == 2)
- *spf = 1152;
- else if(*srate < 32000)
- *spf = 576;
- else
- *spf = 1152;
- }
- }
- if(mpa_layer) *mpa_layer = layer;
- if(chans) *chans = stereo;
- if(br) *br = bitrate;
-
- return framesize;
-}
diff --git a/demux/mp3_hdr.h b/demux/mp3_hdr.h
deleted file mode 100644
index a9b34ac12c..0000000000
--- a/demux/mp3_hdr.h
+++ /dev/null
@@ -1,36 +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_MP3_HDR_H
-#define MPLAYER_MP3_HDR_H
-
-#include <stddef.h>
-
-int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* freq, int* spf, int* mpa_layer, int* br);
-
-#define mp_decode_mp3_header(hbuf) mp_get_mp3_header(hbuf,NULL,NULL,NULL,NULL,NULL)
-
-static inline int mp_check_mp3_header(unsigned int head){
- unsigned char tmp[4] = {head >> 24, head >> 16, head >> 8, head};
- if( (head & 0xffe00000) != 0xffe00000 ||
- (head & 0x00000c00) == 0x00000c00) return 0;
- if(mp_decode_mp3_header(tmp)<=0) return 0;
- return 1;
-}
-
-#endif /* MPLAYER_MP3_HDR_H */
diff --git a/demux/mpeg_hdr.c b/demux/mpeg_hdr.c
deleted file mode 100644
index fcc4a33ecc..0000000000
--- a/demux/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 "core/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/demux/mpeg_hdr.h b/demux/mpeg_hdr.h
deleted file mode 100644
index ccd84bcdb0..0000000000
--- a/demux/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/demux/ms_hdr.h b/demux/ms_hdr.h
index 8e545635dd..7f837a58a4 100644
--- a/demux/ms_hdr.h
+++ b/demux/ms_hdr.h
@@ -22,6 +22,14 @@
#include <sys/types.h>
#include "config.h"
+#include "compat/mpbswap.h"
+
+#ifndef mmioFOURCC
+#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
+ ( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
+ ( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
+#endif
+
#ifndef _WAVEFORMATEX_
#define _WAVEFORMATEX_
typedef struct __attribute__((__packed__)) _WAVEFORMATEX {
diff --git a/demux/parse_es.c b/demux/parse_es.c
deleted file mode 100644
index 8e43446c1f..0000000000
--- a/demux/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 "core/mp_msg.h"
-
-#include "stream/stream.h"
-#include "demux.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/demux/parse_es.h b/demux/parse_es.h
deleted file mode 100644
index af558e379d..0000000000
--- a/demux/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 "demux.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/demux/stheader.h b/demux/stheader.h
index ff98430a65..475d063637 100644
--- a/demux/stheader.h
+++ b/demux/stheader.h
@@ -24,7 +24,6 @@
#include "codec_tags.h"
#include "audio/chmap.h"
-#include "aviheader.h"
#include "ms_hdr.h"
struct MPOpts;
struct demuxer;
@@ -113,7 +112,6 @@ typedef struct sh_audio {
struct af_stream *afilter; // the audio filter stream
const struct ad_functions *ad_driver;
// win32-compatible codec parameters:
- AVIStreamHeader audio;
WAVEFORMATEX *wf;
// note codec extradata may be either under "wf" or "codecdata"
unsigned char *codecdata;
@@ -153,7 +151,6 @@ typedef struct sh_video {
const struct vd_functions *vd_driver;
int vf_initialized; // -1 failed, 0 not done, 1 done
// win32-compatible codec parameters:
- AVIStreamHeader video;
BITMAPINFOHEADER *bih;
} sh_video_t;
@@ -173,9 +170,6 @@ struct sh_audio *new_sh_audio_aid(struct demuxer *demuxer, int id, int aid);
#define new_sh_video(d, i) new_sh_video_vid(d, i, i)
struct sh_video *new_sh_video_vid(struct demuxer *demuxer, int id, int vid);
#define new_sh_sub(d, i) new_sh_sub_sid(d, i, i)
-struct sh_sub *new_sh_sub_sid(struct demuxer *demuxer, int id, int sid);
-struct sh_sub *new_sh_sub_sid_lang(struct demuxer *demuxer, int id, int sid,
- const char *lang);
struct sh_stream *new_sh_stream(struct demuxer *demuxer, enum stream_type type);
// video.c:
diff --git a/demux/video.c b/demux/video.c
index 69749e03d1..48154905fe 100644
--- a/demux/video.c
+++ b/demux/video.c
@@ -32,530 +32,23 @@
#include "stream/stream.h"
#include "demux.h"
#include "stheader.h"
-#include "parse_es.h"
-#include "mpeg_hdr.h"
-
-/* sub_cc (closed captions)*/
-//#include "sub/sub_cc.h"
-
-/* biCompression constant */
-#define BI_RGB 0L
-
-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_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))
- )
- )
- 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
- if(!sh_video->bih) return 0;
- sh_video->format=sh_video->bih->biCompression;
- mp_set_video_codec_from_tag(sh_video);
- 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 = av_malloc(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 = av_malloc(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 = av_malloc(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 = av_malloc(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)
-if (d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_PS ||
- d_video->demuxer->file_format == DEMUXER_TYPE_MPEG_TS)
- mp_set_video_codec_from_tag(sh_video);
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);
- }
- 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. --------------------
@@ -564,14 +57,12 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char**
// override frame_time for variable/unknown FPS formats:
if(!force_fps) switch(demuxer->file_format){
- case DEMUXER_TYPE_GIF:
case DEMUXER_TYPE_MATROSKA:
case DEMUXER_TYPE_MNG:
if(d_video->pts>0 && pts1>0 && d_video->pts>pts1)
frame_time=d_video->pts-pts1;
break;
- case DEMUXER_TYPE_TV:
- case DEMUXER_TYPE_ASF: {
+ case DEMUXER_TYPE_TV: {
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;
if(d>=0){
@@ -599,21 +90,7 @@ 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;