📄 muxer_mpeg.c
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include "config.h"#include "../version.h"#include "../mp_msg.h"#include "bswap.h"#include "aviheader.h"#include "ms_hdr.h"#include "muxer.h"#include "stream.h"#include "demuxer.h"#include "stheader.h"#include "../m_option.h"#include "mpeg_hdr.h"#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 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 8static 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; //dvdstatic uint32_t conf_muxrate = 0; //kb/sstatic 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;static int conf_drop = 0;static int conf_skip_padding = 0;static int conf_reorder = 0;static int conf_telecine = 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; uint32_t temp_ref; uint64_t pts, dts, idur;} 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 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, ts_allframes, has_video, has_audio; int skip_padding; int update_system_header, use_psm; off_t headers_size, data_size; uint64_t scr, vbytes, abytes, init_delay_pts; uint32_t muxrate; uint8_t *buff, *tmp, *residual; uint32_t residual_cnt, 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;} muxer_priv_t;typedef struct { int has_pts, has_dts, pes_is_aligned, type, is_late, min_pes_hlen, psm_fixed; uint64_t pts, last_pts, last_dts, dts, init_pts, init_dts, size, frame_duration, delta_pts, nom_delta_pts, frame_size, last_saved_pts; uint32_t buffer_size; uint8_t pes_priv_headers[4], has_pes_priv_headers; //for A52 and LPCM uint32_t bitrate, rest; int32_t compensate; double delta_clock, timer, aframe_delta_pts, last_dpts; mpeg_frame_t *framebuf; uint16_t framebuf_cnt; uint16_t framebuf_used; uint16_t max_pl_size; int32_t last_tr; int max_tr; uint8_t id, reorder, is_mpeg12, telecine; uint64_t vframes; uint8_t trf; mp_mpeg_header_t picture;} muxer_headers_t;m_option_t mpegopts_conf[] = { {"format", &(conf_mux), CONF_TYPE_STRING, 0, 0 ,0, NULL}, {"size", &(conf_packet_size), CONF_TYPE_INT, CONF_RANGE, 0, 65535, NULL}, {"muxrate", &(conf_muxrate), CONF_TYPE_INT, CONF_RANGE, 0, 12000000, NULL}, //12 Mb/s {"vaspect", &(conf_vaspect), CONF_TYPE_FLOAT, 0, 0, 0, NULL}, {"vframerate", &(conf_vframerate), CONF_TYPE_FLOAT, 0, 0, 0, NULL}, {"vwidth", &(conf_vwidth), CONF_TYPE_INT, CONF_RANGE, 1, 4095, NULL}, {"vheight", &(conf_vheight), CONF_TYPE_INT, CONF_RANGE, 1, 4095, NULL}, {"vpswidth", &(conf_panscan_width), CONF_TYPE_INT, CONF_RANGE, 1, 16383, NULL}, {"vpsheight", &(conf_panscan_height), CONF_TYPE_INT, CONF_RANGE, 1, 16383, NULL}, {"vbitrate", &(conf_vbitrate), CONF_TYPE_INT, CONF_RANGE, 1, 104857599, NULL}, {"init_vpts", &(conf_init_vpts), CONF_TYPE_INT, CONF_RANGE, 100, 700, NULL}, //2*frametime at 60fps {"init_apts", &(conf_init_apts), CONF_TYPE_INT, CONF_RANGE, 100, 700, NULL}, {"vdelay", &conf_init_adelay, CONF_TYPE_INT, CONF_RANGE, 1, 32760, NULL}, {"drop", &conf_drop, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"tsaf", &conf_ts_allframes, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"skip_padding", &conf_skip_padding, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"reorder", &conf_reorder, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"noreorder", &conf_reorder, CONF_TYPE_FLAG, 0, 0, 0, NULL}, {"telecine", &conf_telecine, CONF_TYPE_FLAG, 0, 0, 1, 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 void fix_buffer_params(muxer_priv_t *priv, uint8_t id, 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].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')) );}//from unrarlib.cstatic 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 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 = (mpeg_frame_t *) calloc(num, sizeof(mpeg_frame_t)); if(tmp == NULL) return NULL; for(i=0; i < num; i++) { tmp[i].buffer = (uint8_t *) calloc(1, size); if(tmp[i].buffer == NULL) return NULL; tmp[i].size = 0; tmp[i].alloc_size = size; tmp[i].pts = 0; } return tmp;}static uint32_t calc_pack_hlen(muxer_priv_t *priv, muxer_headers_t *h);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 = (muxer_stream_t*) calloc(1, sizeof(muxer_stream_t)); if(!s) return NULL; // no mem!? if (!(s->b_buffer = malloc(priv->packet_size))) { free (s); return NULL; // no mem?! } s->b_buffer_size = priv->packet_size; s->b_buffer_ptr = 0; s->b_buffer_len = 0; s->priv = (muxer_headers_t*) calloc(1, sizeof(muxer_headers_t)); if(s->priv == NULL) { free(s); return NULL; } spriv = (muxer_headers_t *) s->priv; 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->init_dts = 0; spriv->init_pts = conf_init_vpts * 90 * 1024; spriv->last_pts = spriv->init_pts; spriv->last_saved_pts = 0; spriv->init_dts = spriv->last_dts = spriv->init_pts; spriv->pts = spriv->dts = 0; spriv->last_dpts = spriv->timer; spriv->delta_pts = spriv->nom_delta_pts = 0; spriv->id = 0xe0 + muxer->num_videos; s->ckid = be2me_32 (0x100 + spriv->id); if(priv->is_genmpeg1 || priv->is_genmpeg2) { 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 = (s->h.dwSuggestedBufferSize > 0 ? s->h.dwSuggestedBufferSize : 46*1024); 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); memset(&(spriv->picture), 0, sizeof(spriv->picture)); if(spriv->framebuf == NULL) { mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't allocate initial frames structure, abort!\n"); return NULL; } if(priv->is_xvcd) spriv->min_pes_hlen = 18; else if(priv->is_xsvcd) spriv->min_pes_hlen = 22; spriv->reorder = conf_reorder; 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->pts = 1; spriv->dts = 0; spriv->max_pl_size = priv->packet_size - calc_pack_hlen(priv, spriv); spriv->init_pts = conf_init_apts * 90 * 1024; spriv->pts = spriv->init_pts; spriv->dts = 0; spriv->id = 0xc0 + muxer->num_audios; s->ckid = be2me_32 (0x100 + spriv->id); if(priv->is_genmpeg1 || priv->is_genmpeg2) { 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 = (s->h.dwSuggestedBufferSize > 0 ? s->h.dwSuggestedBufferSize : 4*1024); 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; 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;}static void write_mpeg_ts(unsigned char *b, uint64_t ts, uint8_t mod) { ts >>= 10; 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+49) / 50; 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -