diff options
Diffstat (limited to 'libmpdemux/muxer_mpeg.c')
-rw-r--r-- | libmpdemux/muxer_mpeg.c | 2735 |
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_heade |