summaryrefslogtreecommitdiffstats
path: root/libmpdemux/muxer_mpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmpdemux/muxer_mpeg.c')
-rw-r--r--libmpdemux/muxer_mpeg.c2735
1 files changed, 0 insertions, 2735 deletions
diff --git a/libmpdemux/muxer_mpeg.c b/libmpdemux/muxer_mpeg.c
deleted file mode 100644
index daa1f98a0a..0000000000
--- a/libmpdemux/muxer_mpeg.c
+++ /dev/null
@@ -1,2735 +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 <inttypes.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "config.h"
-#include "mp_msg.h"
-
-#include "aviheader.h"
-#include "ms_hdr.h"
-
-#include "stream/stream.h"
-#include "muxer.h"
-#include "demuxer.h"
-#include "demux_ts.h"
-#include "stheader.h"
-#include "m_option.h"
-#include "aac_hdr.h"
-#include "mpeg_hdr.h"
-#include "mp3_hdr.h"
-
-#ifdef CONFIG_LIBA52
-#include <a52dec/a52.h>
-#endif
-
-#define PACK_HEADER_START_CODE 0x01ba
-#define SYSTEM_HEADER_START_CODE 0x01bb
-#define PSM_START_CODE 0x01bc
-
-#define PES_PRIVATE1 0x01bd
-#define PES_PRIVATE2 0x01bf
-
-#define MUX_MPEG1 1
-#define MUX_MPEG2 2
-
-#define VIDEO_MPEG1 0x10000001
-#define VIDEO_MPEG2 0x10000002
-#define AUDIO_MP2 0x50
-#define AUDIO_MP3 0x55
-#define AUDIO_A52 0x2000
-#define AUDIO_LPCM 0x10001 /* only a placeholder at the moment */
-#define AUDIO_AAC1 0x706D
-//#define AUDIO_AAC2 (short) mmioFOURCC('m','p','4','a')
-#define AUDIO_AAC2 0x504D
-
-#define ASPECT_1_1 1
-#define ASPECT_4_3 2
-#define ASPECT_16_9 3
-#define ASPECT_2_21_1 4
-
-#define FRAMERATE_23976 1
-#define FRAMERATE_24 2
-#define FRAMERATE_25 3
-#define FRAMERATE_2997 4
-#define FRAMERATE_30 5
-#define FRAMERATE_50 6
-#define FRAMERATE_5994 7
-#define FRAMERATE_60 8
-
-static char ftypes[] = {'?', 'I', 'P', 'B'};
-#define FTYPE(x) (ftypes[(x)])
-
-static const char *framerates[] = {
- "unchanged", "23.976", "24", "25", "29.97", "30", "50", "59.94", "60"
-};
-
-static const char *aspect_ratios[] = {
- "unchanged", "1/1", "4/3", "16/9", "2.21/1"
-};
-
-static char *conf_mux = "mpeg2";
-static uint16_t conf_packet_size = 0; //dvd
-static uint32_t conf_muxrate = 0; //kb/s
-static float conf_vaspect = 0;
-static float conf_vframerate = 0;
-static uint32_t conf_vwidth = 0, conf_vheight = 0, conf_panscan_width = 0, conf_panscan_height = 0;
-static uint32_t conf_vbitrate = 0;
-static int conf_init_vpts = 200, conf_init_apts = 200;
-static int conf_ts_allframes = 0;
-static int conf_init_adelay = 0, conf_init_vdelay = 0;
-static int conf_abuf_size = 0;
-static int conf_vbuf_size = 0;
-static int conf_drop = 0;
-static int conf_telecine = 0;
-static int conf_interleaving2 = 0;
-static float conf_telecine_src = 0;
-static float conf_telecine_dest = 0;
-
-enum FRAME_TYPE {
- I_FRAME = 1,
- P_FRAME = 2,
- B_FRAME = 3
-};
-
-typedef struct {
- uint8_t *buffer;
- size_t size;
- size_t alloc_size;
- uint8_t type;
- uint64_t pts, dts, idur;
- uint32_t pos; //start offset for the frame
-} mpeg_frame_t;
-
-typedef struct {
- uint8_t cnt; // how many entries we use
- struct {
- uint8_t id, type;
- uint32_t bufsize;
- uint32_t format;
- } streams[50]; //16 video + 16 audio mpa + 16 audio private + bd/bf for dvd
-} sys_info_t;
-
-typedef struct {
- uint8_t cnt; // how many entries we use
- struct {
- uint8_t id;
- uint8_t type;
- uint32_t format;
- } streams[50]; //16 video + 16 audio mpa + 16 audio private + bd/bf for dvd
-} psm_info_t;
-
-typedef struct {
- int size;
- uint64_t dts;
-} buffer_track_t;
-
-typedef struct {
- uint64_t dts, pts;
- uint64_t frame_dts, frame_pts;
- int len, stflen;
-} pack_stats_t;
-
-typedef struct {
- int mux;
- sys_info_t sys_info;
- psm_info_t psm_info;
- uint16_t packet_size;
- int is_dvd, is_xvcd, is_xsvcd, is_genmpeg1, is_genmpeg2, rawpes, ts_allframes, has_video, has_audio;
- int update_system_header, use_psm;
- off_t headers_size, data_size;
- uint64_t scr;
- uint64_t delta_scr;
- uint64_t last_psm_scr;
- uint32_t muxrate;
- uint8_t *buff;
- uint32_t headers_cnt;
- double init_adelay;
- int drop;
-
- //video patching parameters
- uint8_t vaspect, vframerate;
- uint16_t vwidth, vheight, panscan_width, panscan_height;
- uint32_t vbitrate;
- int patch_seq, patch_sde;
- int psm_streams_cnt;
-
-//2 million frames are enough
-#define MAX_PATTERN_LENGTH 2000000
- uint8_t bff_mask[MAX_PATTERN_LENGTH];
-} muxer_priv_t;
-
-
-typedef struct {
- int has_pts, has_dts, pes_is_aligned, type, min_pes_hlen;
- int delay_rff;
- uint64_t pts, last_pts, last_dts, dts, size, frame_duration, delta_pts, nom_delta_pts, last_saved_pts;
- uint32_t buffer_size;
- double delta_clock, timer;
- int drop_delayed_frames;
- mpeg_frame_t *framebuf;
- uint16_t framebuf_cnt;
- uint16_t framebuf_used;
- int32_t last_tr;
- int max_tr;
- uint8_t id, is_mpeg12, telecine;
- uint64_t vframes;
- int64_t display_frame;
- mp_mpeg_header_t picture;
- int max_buffer_size;
- buffer_track_t *buffer_track;
- int track_pos, track_len, track_bufsize; //pos and len control the array, bufsize is the size of the buffer
- unsigned char *pack;
- int pack_offset, pes_offset, pes_set, payload_offset;
- int frames;
- int last_frame_rest; //the rest of the previous frame
- int is_ready;
- int mpa_layer;
-} muxer_headers_t;
-
-#define PULLDOWN32 1
-#define TELECINE_FILM2PAL 2
-#define TELECINE_DGPULLDOWN 3
-
-const m_option_t mpegopts_conf[] = {
- {"format", &(conf_mux), CONF_TYPE_STRING, M_OPT_GLOBAL, 0 ,0, NULL},
- {"size", &(conf_packet_size), CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 0, 65535, NULL},
- {"muxrate", &(conf_muxrate), CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 0, 12000000, NULL}, //12 Mb/s
- {"vaspect", &(conf_vaspect), CONF_TYPE_FLOAT, M_OPT_GLOBAL, 0, 0, NULL},
- {"vframerate", &(conf_vframerate), CONF_TYPE_FLOAT, M_OPT_GLOBAL, 0, 0, NULL},
- {"vwidth", &(conf_vwidth), CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 1, 4095, NULL},
- {"vheight", &(conf_vheight), CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 1, 4095, NULL},
- {"vpswidth", &(conf_panscan_width), CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 1, 16383, NULL},
- {"vpsheight", &(conf_panscan_height), CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 1, 16383, NULL},
- {"vbitrate", &(conf_vbitrate), CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 1, 104857599, NULL},
- {"vdelay", &conf_init_vdelay, CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 0, 32760, NULL},
- {"adelay", &conf_init_adelay, CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 0, 32760, NULL},
- {"vbuf_size", &conf_vbuf_size, CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 40, 1194, NULL},
- {"abuf_size", &conf_abuf_size, CONF_TYPE_INT, M_OPT_GLOBAL|M_OPT_RANGE, 4, 64, NULL},
- {"drop", &conf_drop, CONF_TYPE_FLAG, M_OPT_GLOBAL, 0, 1, NULL},
- {"tsaf", &conf_ts_allframes, CONF_TYPE_FLAG, M_OPT_GLOBAL, 0, 1, NULL},
- {"telecine", &conf_telecine, CONF_TYPE_FLAG, M_OPT_GLOBAL, 0, PULLDOWN32, NULL},
- {"interleaving2", &conf_interleaving2, CONF_TYPE_FLAG, M_OPT_GLOBAL, 0, 1, NULL},
- {"film2pal", &conf_telecine, CONF_TYPE_FLAG, M_OPT_GLOBAL, 0, TELECINE_FILM2PAL, NULL},
- {"tele_src", &(conf_telecine_src), CONF_TYPE_FLOAT, M_OPT_GLOBAL, 0, 0, NULL},
- {"tele_dest", &(conf_telecine_dest), CONF_TYPE_FLOAT, M_OPT_GLOBAL, 0, 0, NULL},
- {NULL, NULL, 0, 0, 0, 0, NULL}
-};
-
-static void fix_audio_sys_header(muxer_priv_t *priv, uint8_t id, uint8_t newid, uint32_t size)
-{
- uint8_t i;
-
- for(i = 0; i < priv->sys_info.cnt; i++)
- {
- if(priv->sys_info.streams[i].id == id)
- {
- priv->sys_info.streams[i].id = newid;
- priv->sys_info.streams[i].type = 1;
- priv->sys_info.streams[i].bufsize = size;
- }
- }
-}
-
-static inline int is_mpeg1(uint32_t x)
-{
- return
- (x == 0x10000001) ||
- (x == mmioFOURCC('m','p','g','1')) ||
- (x == mmioFOURCC('M','P','G','1'));
-}
-
-static inline int is_mpeg2(uint32_t x)
-{
- return
- (x == 0x10000002) ||
- (x == mmioFOURCC('m','p','g','2')) ||
- (x == mmioFOURCC('M','P','G','2')) ||
- (x == mmioFOURCC('m','p','e','g')) ||
- (x == mmioFOURCC('M','P','E','G'));
-}
-
-static inline int is_mpeg4(uint32_t x)
-{
- return
- (x == 0x10000004) ||
- (x == mmioFOURCC('d','i','v','x')) ||
- (x == mmioFOURCC('D','I','V','X')) ||
- (x == mmioFOURCC('x','v','i','d')) ||
- (x == mmioFOURCC('X','V','I','D')) ||
- (x == mmioFOURCC('X','v','i','D')) ||
- (x == mmioFOURCC('x','v','i','x')) ||
- (x == mmioFOURCC('X','V','I','X')) ||
- (x == mmioFOURCC('m','p','4','v')) ||
- (x == mmioFOURCC('M','P','4','V')) ||
- (x == mmioFOURCC('F', 'M','P','4')) ||
- (x == mmioFOURCC('f', 'm','p','4')) ||
- (x == mmioFOURCC('D', 'X','5','0')) ||
- (x == mmioFOURCC('d', 'x','5','0'));
-}
-
-//from unrarlib.c
-static uint32_t CalcCRC32(uint8_t *buff, uint32_t size)
-{
- uint32_t i, j, CRCTab[256], crc;
-
- for(i = 0;i < 256; i++)
- {
- for(crc = i, j = 0; j < 8; j++)
- crc= (crc & 1) ? (crc >> 1)^0xEDB88320L : (crc >> 1);
- CRCTab[i] = crc;
- }
-
-
- crc = 0xffffffff;
- for(i = 0; i < size; i++)
- crc = (crc << 8) ^ CRCTab[((crc >> 24) ^ buff[i]) & 0xff];
-
- return crc;
-}
-
-
-static void add_to_psm(muxer_priv_t *priv, uint8_t id, uint32_t format)
-{
- uint8_t i;
-
- i = priv->psm_info.cnt;
- priv->psm_info.streams[i].id = id;
- priv->psm_info.streams[i].format = format;
-
- if(is_mpeg1(format))
- priv->psm_info.streams[i].type = 0x01;
- else if(is_mpeg2(format))
- priv->psm_info.streams[i].type = 0x02;
- else if(is_mpeg4(format))
- priv->psm_info.streams[i].type = 0x10;
- else if(format == AUDIO_MP2 || format == AUDIO_MP3)
- priv->psm_info.streams[i].type = 0x03;
- else if(format == AUDIO_AAC1 || format == AUDIO_AAC2)
- priv->psm_info.streams[i].type = 0x0f;
- else
- priv->psm_info.streams[i].type = 0x81;
-
- if(format == AUDIO_A52)
- memcpy((char*) &(priv->psm_info.streams[i].format), "AC-3", 4);
-
- priv->psm_info.cnt++;
-}
-
-
-static mpeg_frame_t *init_frames(uint16_t num, size_t size)
-{
- mpeg_frame_t *tmp;
- uint16_t i;
-
- tmp = calloc(num, sizeof(mpeg_frame_t));
- if(tmp == NULL)
- return NULL;
-
- for(i=0; i < num; i++)
- {
- tmp[i].buffer = calloc(1, size);
- if(tmp[i].buffer == NULL)
- return NULL;
- tmp[i].size = 0;
- tmp[i].pos = 0;
- tmp[i].alloc_size = size;
- tmp[i].pts = 0;
- }
-
- return tmp;
-}
-
-static int add_frame(muxer_headers_t *spriv, uint64_t idur, uint8_t *ptr, int len, uint8_t pt, uint64_t dts, uint64_t pts);
-
-static muxer_stream_t* mpegfile_new_stream(muxer_t *muxer,int type){
- muxer_priv_t *priv = (muxer_priv_t*) muxer->priv;
- muxer_stream_t *s;
- muxer_headers_t *spriv;
-
- if (!muxer) return NULL;
- if(muxer->avih.dwStreams>=MUXER_MAX_STREAMS){
- mp_msg(MSGT_MUXER, MSGL_ERR, "Too many streams! increase MUXER_MAX_STREAMS !\n");
- return NULL;
- }
- switch (type) {
- case MUXER_TYPE_VIDEO:
- if (muxer->num_videos >= 16) {
- mp_msg(MSGT_MUXER, MSGL_ERR, "MPEG files can't contain more than 16 video streams!\n");
- return NULL;
- }
- break;
- case MUXER_TYPE_AUDIO:
- if (muxer->num_audios >= 16) {
- mp_msg(MSGT_MUXER, MSGL_ERR, "MPEG files can't contain more than 16 audio streams!\n");
- return NULL;
- }
- break;
- default:
- mp_msg(MSGT_MUXER, MSGL_ERR, "Unknown stream type!\n");
- return NULL;
- }
- s = calloc(1, sizeof(muxer_stream_t));
- if(!s) return NULL; // no mem!?
- if (!(s->b_buffer = malloc(priv->packet_size)))
- goto init_fail;
- s->b_buffer_size = priv->packet_size;
- s->b_buffer_ptr = 0;
- s->b_buffer_len = 0;
- s->priv = calloc(1, sizeof(muxer_headers_t));
- if(s->priv == NULL)
- goto init_fail;
- spriv = (muxer_headers_t *) s->priv;
- spriv->pack = malloc(priv->packet_size);
- if(! spriv->pack)
- goto init_fail;
- spriv->buffer_track = calloc(1, 4096*sizeof(buffer_track_t));
- if(!spriv->buffer_track)
- goto init_fail;
- spriv->track_pos = 0;
- spriv->track_len = 4096;
- muxer->streams[muxer->avih.dwStreams]=s;
- s->type=type;
- s->id=muxer->avih.dwStreams;
- s->muxer=muxer;
-
- if (type == MUXER_TYPE_VIDEO) {
- spriv->type = 1;
- spriv->last_pts = conf_init_vpts * 90 * 300;
- if(conf_init_vdelay) {
- spriv->last_dts += conf_init_vdelay * 90 * 300;
- spriv->last_pts += conf_init_vdelay * 90 * 300;
- }
- spriv->id = 0xe0 + muxer->num_videos;
- s->ckid = be2me_32 (0x100 + spriv->id);
- if(priv->is_genmpeg1 || priv->is_genmpeg2) {
- int v = (conf_vbuf_size ? conf_vbuf_size*1024 :
- (s->h.dwSuggestedBufferSize ? s->h.dwSuggestedBufferSize : 46*1024));
- int n = priv->sys_info.cnt;
-
- priv->sys_info.streams[n].id = spriv->id;
- priv->sys_info.streams[n].type = 1;
- priv->sys_info.streams[n].bufsize = v;
- priv->sys_info.cnt++;
- }
- muxer->num_videos++;
- priv->has_video++;
- s->h.fccType=streamtypeVIDEO;
- if(!muxer->def_v) muxer->def_v=s;
- spriv->framebuf_cnt = 30;
- spriv->framebuf_used = 0;
- spriv->framebuf = init_frames(spriv->framebuf_cnt, (size_t) 5000);
- if(spriv->framebuf == NULL) {
- mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't allocate initial frames structure, abort!\n");
- goto init_fail;
- }
- memset(&(spriv->picture), 0, sizeof(spriv->picture));
- if(priv->is_xvcd)
- spriv->min_pes_hlen = 18;
- else if(priv->is_xsvcd)
- spriv->min_pes_hlen = 22;
- spriv->telecine = conf_telecine;
- mp_msg (MSGT_MUXER, MSGL_DBG2, "Added video stream %d, ckid=%X\n", muxer->num_videos, s->ckid);
- } else { // MUXER_TYPE_AUDIO
- spriv->type = 0;
- spriv->drop_delayed_frames = conf_drop;
- spriv->last_pts = conf_init_apts * 90 * 300;
- if(conf_init_adelay && ! spriv->drop_delayed_frames)
- spriv->last_pts += conf_init_adelay * 90 * 300;
- spriv->pts = spriv->last_pts;
- spriv->id = 0xc0 + muxer->num_audios;
- s->ckid = be2me_32 (0x100 + spriv->id);
- if(priv->is_genmpeg1 || priv->is_genmpeg2) {
- int a1 = (conf_abuf_size ? conf_abuf_size*1024 :
- (s->h.dwSuggestedBufferSize ? s->h.dwSuggestedBufferSize : 4*1024));
- int n = priv->sys_info.cnt;
-
- priv->sys_info.streams[n].id = spriv->id;
- priv->sys_info.streams[n].type = 0;
- priv->sys_info.streams[n].bufsize = a1;
- priv->sys_info.cnt++;
- }
- if(priv->is_xvcd)
- spriv->min_pes_hlen = 13;
- else if(priv->is_xsvcd)
- spriv->min_pes_hlen = 17;
-
- muxer->num_audios++;
- priv->has_audio++;
- s->h.fccType=streamtypeAUDIO;
-
- spriv->framebuf_cnt = 30;
- spriv->framebuf_used = 0;
- spriv->framebuf = init_frames(spriv->framebuf_cnt, (size_t) 2048);
- if(spriv->framebuf == NULL) {
- mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't allocate initial frames structure, abort!\n");
- goto init_fail;
- }
-
- mp_msg (MSGT_MUXER, MSGL_DBG2, "Added audio stream %d, ckid=%X\n", s->id - muxer->num_videos + 1, s->ckid);
- }
- muxer->avih.dwStreams++;
- return s;
-
-init_fail:
- if(s)
- {
- if(s->priv)
- {
- spriv = s->priv;
- if(spriv->pack)
- free(spriv->pack);
- if(spriv->buffer_track)
- free(spriv->buffer_track);
- free(s->priv);
- }
- if(s->b_buffer)
- free(s->b_buffer);
- free(s);
- }
- return NULL;
-}
-
-static void write_mpeg_ts(unsigned char *b, uint64_t ts, uint8_t mod) {
- ts /= 300;
- b[0] = mod | ((ts >> 29) & 0xf) | 1;
- b[1] = (ts >> 22) & 0xff;
- b[2] = ((ts >> 14) & 0xff) | 1;
- b[3] = (ts >> 7) & 0xff;
- b[4] = ((ts << 1) & 0xff) | 1;
-}
-
-
-static void write_mpeg_rate(int type, unsigned char *b, unsigned int rate)
-{
- rate = ((rate*8)+399) / 400;
-
- if(type == MUX_MPEG1)
- {
- b[0] = ((rate >> 15) & 0x7f) | 0x80;
- b[1] = (rate >> 7) & 0xff;
- b[2] = ((rate << 1) & 0xff) | 1;
- }
- else
- {
- b[0] = (rate >> 14);
- b[1] = (rate >> 6) & 0xff;
- b[2] = ((rate & 0x3f) << 2) | 0x03;
- }
-}
-
-
-static void write_mpeg_std(unsigned char *b, unsigned int size, unsigned int type, uint8_t mod)
-{
- //type = 0:mpeg audio/128, 1:video and pes private streams (including ac3/dts/lpcm)/1024
- if(type == 0) //audio
- size = (size + 127) / 128;
- else //video or other
- size = ((size + 1023) / 1024);
-
- if(! size)
- size++;
-
- b[0] = ((size >> 8) & 0x3f) | (type==1 ? 0x60 : 0x40) | mod;
- b[1] = size & 0xff;
-}
-
-static void write_mpeg2_scr(unsigned char *b, uint64_t ts)
-{
- uint16_t t1, t2, t3, scr_ext;
- scr_ext = ts % 300ULL;
- ts /= 300ULL;
- ts &= 0x1FFFFFFFFULL; //33 bits
- t1 = (ts >> 30) & 0x7;
- t2 = (ts >> 15) & 0x7fff;
- t3 = ts & 0x7fff;
-
- b[0] = (t1 << 3 ) | 0x44 | ((t2 >> 13) & 0x3);
- b[1] = (t2 >> 5);
- b[2] = (t2 & 0x1f) << 3 | 0x4 | ((t3 >> 13) & 0x3);
- b[3] = (t3 >> 5);
- b[4] = (t3 & 0x1f) << 3 | ((scr_ext >> 7) & 0x03) | 0x4;
- b[5] = ((scr_ext << 1) & 0xFF) | 1;
-}
-
-
-static int write_mpeg_pack_header(muxer_t *muxer, char *buff)
-{
- int len;
- muxer_priv_t *priv;
-
- priv = (muxer_priv_t *) muxer->priv;
- *(uint32_t *)buff = be2me_32(PACK_HEADER_START_CODE);
- if(priv->mux==MUX_MPEG1)
- {
- write_mpeg_ts(&buff[4], priv->scr, 0x20); // 0010 and SCR
- write_mpeg_rate(priv->mux, &buff[9], muxer->sysrate);
- len = 12;
- }
- else
- {
- write_mpeg2_scr(&buff[4], priv->scr); // 0010 and SCR
- write_mpeg_rate(priv->mux, &buff[10], muxer->sysrate);
- buff[13] = 0xf8; //5 bits reserved + 3 set to 0 to indicate 0 stuffing bytes
- len = 14;
- }
-
- return len;
-}
-
-
-static int write_mpeg_system_header(muxer_t *muxer, char *buff)
-{
- int len;
- uint8_t i;
- muxer_priv_t *priv;
- priv = (muxer_priv_t *) muxer->priv;
-
- len = 0;
- *(uint32_t *)(&buff[len]) = be2me_32(SYSTEM_HEADER_START_CODE);
- len += 4;
- *(uint16_t *)(&buff[len]) = 0; //fake length, we'll fix it later
- len += 2;
- write_mpeg_rate(MUX_MPEG1, &buff[len], muxer->sysrate);
- len += 3;
-
- buff[len++] = 0x4 | (priv->is_xvcd ? 1 : 0); //1 audio stream bound, no fixed, CSPS only for xvcd
- //stolen from libavformat
- if(priv->is_xvcd || priv->is_dvd)
- buff[len++] = 0xe1; //system_audio_lock, system_video_lock, marker, 1 video stream bound
- else
- buff[len++] = 0x21; //marker, 1 video stream bound
-
- buff[len++] = ((priv->mux == MUX_MPEG1) ? 0xff : 0x7f); //in mpeg2 there's the packet rate restriction
-
- for(i = 0; i < priv->sys_info.cnt; i++)
- {
- buff[len++] = priv->sys_info.streams[i].id;
- write_mpeg_std(&buff[len], priv->sys_info.streams[i].bufsize, priv->sys_info.streams[i].type,
- (priv->sys_info.streams[i].type == 1 ? 0xe0: 0xc0));
- len += 2;
- }
-
- *(uint16_t *)(&buff[4]) = be2me_16(len - 6); // length field fixed
-
- return len;
-}
-
-static int write_mpeg_psm(muxer_t *muxer, char *buff)
-{
- int len;
- uint8_t i;
- uint16_t dlen;
- muxer_priv_t *priv;
- priv = (muxer_priv_t *) muxer->priv;
-
- len = 0;
- *(uint32_t *)(&buff[len]) = be2me_32(PSM_START_CODE);
- len += 4;
- *(uint16_t *)(&buff[len]) = 0; //fake length, we'll fix it later
- len += 2;
- buff[len++] = 0xe0; //1 current, 2 bits reserved, 5 version 0
- buff[len++] = 0xff; //7 reserved, 1 marker
- buff[len] = buff[len+1] = 0; //length of the program descriptors (unused)
- len += 2;
- *(uint16_t *)(&buff[len]) = 0; //length of the es descriptors
- len += 2;
-
- dlen = 0;
- for(i = 0; i < priv->psm_info.cnt; i++)
- {
- if(
- (priv->psm_info.streams[i].id == 0xbd) ||
- (priv->psm_info.streams[i].id >= 0xe0 && priv->psm_info.streams[i].id <= 0xef) ||
- (priv->psm_info.streams[i].id >= 0xc0 && priv->psm_info.streams[i].id <= 0xcf)
- )
- {
- buff[len++] = priv->psm_info.streams[i].type;
- buff[len++] = priv->psm_info.streams[i].id;
- buff[len++] = 0; //len of descriptor upper ...
- buff[len++] = 0; //... lower
-
- dlen += 4;
- }
- }
- *(uint16_t *)(&buff[10]) = be2me_16(dlen); //length of the es descriptors
-
- *(uint16_t *)(&buff[4]) = be2me_16(len - 6 + 4); // length field fixed, including size of CRC32
-
- *(uint32_t *)(&buff[len]) = be2me_32(CalcCRC32(buff, len));
-
- len += 4; //for crc
-
- return len;
-}
-
-static int psm_is_late(muxer_priv_t *priv)
-{
- return !priv->data_size || (priv->scr >= priv->last_psm_scr + 27000000ULL);
-}
-
-static int write_mpeg_pes_header(muxer_headers_t *h, uint8_t *pes_id, uint8_t *buff, uint16_t plen, int stuffing_len, int mux_type)
-{
- int len;
-
- len = 0;
- memcpy(&buff[len], pes_id, 4);
- len += 4;
-
- buff[len] = buff[len+1] = 0; //fake len
- len += 2;
-
- if(mux_type == MUX_MPEG1)
- {
- if(stuffing_len > 0)
- {
- memset(&buff[len], 0xff, stuffing_len);
- len += stuffing_len;
- }
-
- if(h->buffer_size > 0)
- {
- write_mpeg_std(&buff[len], h->buffer_size, h->type, 0x40); // 01 is pes1 format
- len += 2;
- }
- }
- else //MPEG2
- {
- buff[len] = (h->pes_is_aligned ? 0x84 : 0x80); //0x10...
- len++;
- buff[len] = ((h->buffer_size > 0) ? 1 : 0) | (h->pts ? (h->dts ? 0xC0 : 0x80) : 0); //pes extension + pts/dts flags
- len++;
- buff[len] = (h->pts ? (h->dts ? 10 : 5) : 0) + ((h->buffer_size > 0) ? 3 : 0) + stuffing_len;//pts + std + stuffing
- len++;
- }
-
-
- if(h->pts)
- {
- write_mpeg_ts(&buff[len], h->pts, (h->dts ? 0x30 : 0x20)); // 001x and both PTS/DTS
- len += 5;
-
- if(h->dts)
- {
- write_mpeg_ts(&buff[len], h->dts, 0x10); // 0001 before DTS
- len += 5;
- }
- }
- else
- {
- if(mux_type == MUX_MPEG1)
- {
- buff[len] = 0x0f;
- len += 1;
- }
- }
-
-
- if(mux_type == MUX_MPEG2)
- {
- if(h->buffer_size > 0)
- {
- buff[len] = 0x1e; //std flag
- len++;
-
- write_mpeg_std(&buff[len], h->buffer_size, h->type, 0x40);
- len += 2;
- }
-
- if(stuffing_len > 0)
- {
- memset(&buff[len], 0xff, stuffing_len);
- len += stuffing_len;
- }
- }
-
- *((uint16_t*) &buff[4]) = be2me_16(len + plen - 6); //fix pes packet size
- return len;
-}
-
-
-static void write_pes_padding(uint8_t *buff, uint16_t len)
-{
- //6 header bytes + len-6 0xff chars
- buff[0] = buff[1] = 0;
- buff[2] = 1;
- buff[3] = 0xbe;
- *((uint16_t*) &buff[4]) = be2me_16(len - 6);
- memset(&buff[6], 0xff, len - 6);
-}
-
-
-static int write_nav_pack(uint8_t *buff)
-{
- // concatenation of pes_private2 + 03d4 x 0 and pes_private2 + 03fa x 0
- int len;
-
- mp_msg(MSGT_MUXER, MSGL_DBG3, "NAV\n");
- len = 0;
- *(uint32_t *)(&buff[len]) = be2me_32(PES_PRIVATE2);
- len += 4;
- buff[len++] = 0x3;
- buff[len++] = 0xd4;
- memset(&buff[len], 0, 0x03d4);
- len += 0x03d4;
-
- *(uint32_t *)(&buff[len]) = be2me_32(PES_PRIVATE2);
- len += 4;
- buff[len++] = 0x3;
- buff[len++] = 0xfa;
- memset(&buff[len], 0, 0x03fa);
- len += 0x03fa;
-
- return len;
-}
-
-static unsigned int calc_psm_len(muxer_priv_t *priv)
-{
- return 16 + 4*(priv->psm_info.cnt);
-}
-
-static uint32_t calc_pes_hlen(int format, muxer_headers_t *h, muxer_priv_t *priv)
-{
- uint32_t len;
-
- if(format == MUX_MPEG1)
- len = 6;
- else
- len = 9;
-
- if(h->pts)
- {
- len += 5;
- if(h->dts)
- len += 5;
- }
- else if(format == MUX_MPEG1)
- len += 1;
-
- if(h->buffer_size > 0)
- {
- if(format == MUX_MPEG2)
- len += 3;
- else
- len += 2;
- }
-
- //len = max(h->min_pes_hlen, len);
-
- return len;
-}
-
-
-static int write_mpeg_pack(muxer_t *muxer, muxer_stream_t *s, stream_t *stream, int isoend)
-{
- size_t tot, offset;
- muxer_priv_t *priv;
- unsigned char *buff;
- int stuffing_len;
-
- priv = (muxer_priv_t *) muxer->priv;
- buff = priv->buff;
-
- if(isoend)
- {
- offset = priv->packet_size - 4;
- write_pes_padding(buff, offset);
- buff[offset + 0] = buff[offset + 1] = 0;
- buff[offset + 2] = 1;
- buff[offset + 3] = 0xb9;
-
- stream_write_buffer(stream, buff, priv->packet_size);
- return 1;
- }
- else //FAKE DVD NAV PACK
- {
- offset = write_mpeg_pack_header(muxer, buff);
- offset += write_mpeg_system_header(muxer, &buff[offset]);
-
- //priv->update_system_header = 0;
-
- if(priv->is_dvd)
- offset += write_nav_pack(&buff[offset]);
-
- stuffing_len = priv->packet_size - offset;
- if(stuffing_len > 0)
- {
- //insert a PES padding packet
- write_pes_padding(&buff[offset], stuffing_len);
- offset += stuffing_len;
- }
-
- stream_write_buffer(stream, buff, offset);
- priv->headers_size += offset;
- tot = offset;
- muxer->movi_end += tot;
-
- return tot;
- }
-}
-
-static void update_demux_bufsize(muxer_headers_t *spriv, uint64_t dts, int framelen, int type)
-{
- int dim = (spriv->track_len+16)*sizeof(buffer_track_t);
-
- if(spriv->track_pos+1 >= spriv->track_len)
- {
- buffer_track_t *tmp = realloc(spriv->buffer_track, dim);
- if(!tmp)
- {
- mp_msg(MSGT_MUXER, MSGL_ERR, "\r\nERROR, couldn't realloc %d bytes for tracking buffer\r\n", dim);
- return;
- }
- spriv->buffer_track = tmp;
- memset(&(spriv->buffer_track[spriv->track_pos+1]), 0, 16*sizeof(buffer_track_t));
- spriv->track_len += 16;
- }
-
- spriv->buffer_track[spriv->track_pos].size = framelen;
- spriv->buffer_track[spriv->track_pos].dts = dts; //must be dts
-
- spriv->track_pos++;
-}
-
-static void fix_a52_headers(muxer_stream_t *s)
-{
- muxer_headers_t *spriv = s->priv;
- int x = spriv->payload_offset;
-
- spriv->pack[x+0] = 0x80;
- spriv->pack[x+1] = spriv->frames;
- if(spriv->frames)
- {
- spriv->pack[x+2] = ((spriv->last_frame_rest+1) >> 8) & 0xff; //256 * 0 ...
- spriv->pack[x+3] = (spriv->last_frame_rest+1) & 0xff; // + 1 byte(s) to skip
- }
- else
- spriv->pack[x+2] = spriv->pack[x+3] = 0;
-}
-
-static inline void remove_frames(muxer_headers_t *spriv, int n)
-{
- mpeg_frame_t tmp;
- int i;
-
- for(i = n; i < spriv->framebuf_used; i++)
- {
- tmp = spriv->framebuf[i - n];
- spriv->framebuf[i - n] = spriv->framebuf[i];
- spriv->framebuf[i] = tmp;
- }
- spriv->framebuf_used -= n;
-}
-
-static int calc_packet_len(muxer_stream_t *s, int psize, int finalize)
-{
- muxer_headers_t *spriv = s->priv;
- int n, len, frpos, m;
-
- n = len = 0;
- frpos = spriv->framebuf[0].pos;
- while(len < psize && n < spriv->framebuf_used)
- {
- if(!frpos && len>0 && s->type == MUXER_TYPE_VIDEO && spriv->framebuf[n].type==I_FRAME)
- return len;
- m = FFMIN(spriv->framebuf[n].size - frpos, psize - len);
- len += m;
- frpos += m;
- if(frpos == spriv->framebuf[n].size)
- {
- frpos = 0;
- n++;
- }
- }
-
- if(len < psize && !finalize)
- return 0;
- return len;
-}
-
-static int find_packet_timestamps(muxer_priv_t *priv, muxer_stream_t *s, unsigned int start, uint64_t *dts, uint64_t *pts)
-{
- muxer_headers_t *spriv = s->priv;
- int i, m, pes_hlen, ret, threshold;
- uint64_t spts, sdts, dpts;
-
- if(!spriv->framebuf_used)
- return 0;
-
- spts = spriv->pts;
- sdts = spriv->dts;
- spriv->dts = spriv->pts = 0;
- ret = 0;
- if(spriv->framebuf[0].pos == 0) // start of frame
- i = 0;
- else
- {
- pes_hlen = calc_pes_hlen(priv->mux, spriv, priv);
-
- if(pes_hlen < spriv->min_pes_hlen)
- pes_hlen = spriv->min_pes_hlen;
-
- m = spriv->framebuf[0].size - spriv->framebuf[0].pos;
-
- if(start + pes_hlen + m >= priv->packet_size) //spriv->pack_offset
- i = -1; //this pack won't have a pts: no space available
- else
- {
- if(spriv->framebuf_used < 2)
- goto fail;
-
- if(spriv->framebuf[1].pts == spriv->framebuf[1].dts)
- threshold = 5;
- else
- threshold = 10;
-
- //headers+frame 0 < space available including timestamps
- if(start + pes_hlen + m < priv->packet_size - threshold)
- i = 1;
- else
- i = -1;
- }
- }
-
- if(i > -1)
- {
- dpts = FFMAX(spriv->last_saved_pts, spriv->framebuf[i].pts) -
- FFMIN(spriv->last_saved_pts, spriv->framebuf[i].pts) +
- spriv->framebuf[0].idur;
-
- if(s->type != MUXER_TYPE_VIDEO)
- ret = 1;
- else if((spriv->framebuf[i].type == I_FRAME || priv->ts_allframes || dpts >= 36000*300)) //0.4 seconds
- ret = 1;
-
- if(ret)
- {
- *pts = spriv->framebuf[i].pts;
- *dts = spriv->framebuf[i].dts;
- if(*dts == *pts)
- *dts = 0;
- }
- }
-
-fail:
- spriv->pts = spts;
- spriv->dts = sdts;
- return ret;
-}
-
-static int get_packet_stats(muxer_priv_t *priv, muxer_stream_t *s, pack_stats_t *p, int finalize)
-{
- muxer_headers_t *spriv = s->priv;
- int len, len2, pack_hlen, pes_hlen, hlen, target, stflen, stuffing_len;
- uint64_t pts, dts;
-
- spriv->pts = spriv->dts = 0;
- p->dts = p->pts = p->frame_pts = p->frame_dts = 0;
- p->len = 0;
-
- if(priv->rawpes)
- pack_hlen = 0;
- else if(priv->mux == MUX_MPEG1)
- pack_hlen = 12;
- else
- pack_hlen = 14;
- if(priv->use_psm && psm_is_late(priv))
- pack_hlen += calc_psm_len(priv);
-
- if(find_packet_timestamps(priv, s, pack_hlen, &dts, &pts))
- {
- p->pts = p->frame_pts = pts;
- p->dts = p->frame_dts = dts;
-
- spriv->pts = pts;
- spriv->dts = dts;
- }
- pes_hlen = calc_pes_hlen(priv->mux, spriv, priv);
-
- p->stflen = stflen = (spriv->min_pes_hlen > pes_hlen ? spriv->min_pes_hlen - pes_hlen : 0);
-
- target = len = priv->packet_size - pack_hlen - pes_hlen - stflen; //max space available
- if(s->type == MUXER_TYPE_AUDIO && s->wf->wFormatTag == AUDIO_A52)
- hlen = 4;
- else
- hlen = 0;
-
- len -= hlen;
- target -= hlen;
-
- len2 = calc_packet_len(s, target, finalize);
- if(!len2 || (len2 < target && s->type == MUXER_TYPE_AUDIO && !finalize))
- {
- //p->len = 0;
- //p->dts = p->pts = 0;
- spriv->pts = spriv->dts = 0;
- //fprintf(stderr, "\r\nLEN2: %d, target: %d, type: %d\r\n", len2, target, s->type);
- return 0;
- }
-
- len = len2;
- stuffing_len = 0;
- if(len < target)
- {
- if(s->type == MUXER_TYPE_VIDEO)
- {
- if(spriv->pts)
- target += 5;
- if(spriv->dts)
- target += 5;
- spriv->pts = spriv->dts = 0;
- p->pts = p->dts = 0;
- }
-
- stuffing_len = target - len;
- if(stuffing_len > 0 && stuffing_len < 7)
- {
- if(stflen + stuffing_len > 16)
- {
- int x = 7 - stuffing_len;
- stflen -= x;
- stuffing_len += x;
- }
- else
- {
- stflen += stuffing_len;
- stuffing_len = 0;
- }
- }
- }
-
- len += hlen;
-
- p->len = len;
- p->stflen = stflen;
-
- return p->len;
-}
-
-static int fill_packet(muxer_t *muxer, muxer_stream_t *s, int finalize)
-{
- //try to fill a packet as much as possible
- //spriv->pack_offset is the start position initialized to 0
- //data is taken from spriv->framebuf
- //if audio and a52 insert the headers
- muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
- muxer_headers_t *spriv = (muxer_headers_t *) s->priv;
- int len, m, n, dvd_pack = 0;
- int write_psm = 0;
- mpeg_frame_t *frm;
- pack_stats_t p;
-
- spriv->dts = spriv->pts = 0;
-
- if(! spriv->framebuf_used)
- {
- spriv->pack_offset = 0;
- return 0;
- }
-
- if(!spriv->pack_offset)
- {
- if(priv->rawpes)
- spriv->pack_offset = 0;
- else
- spriv->pack_offset = write_mpeg_pack_header(muxer, spriv->pack);
- if(priv->update_system_header && (priv->is_genmpeg1 || priv->is_genmpeg2))
- {
- spriv->pack_offset += write_mpeg_system_header(muxer, &spriv->pack[spriv->pack_offset]);
- priv->update_system_header = 0;
- }
-
- if(priv->use_psm && psm_is_late(priv))
- {
- spriv->pack_offset += write_mpeg_psm(muxer, &spriv->pack[spriv->pack_offset]);
- wr