muxer_mpeg.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 2,496 行 · 第 1/5 页

C
2,496
字号
#include <mplaylib.h>#include <mplaylib.h>#include <inttypes.h>#include <mplaylib.h>#include <sys/types.h>#include "config.h"#include "version.h"#include "mp_msg.h"#include "help_mp.h"#include "aviheader.h"#include "ms_hdr.h"#include "stream/stream.h"#include "muxer.h"#include "demuxer.h"#include "stheader.h"#include "m_option.h"#include "mpeg_hdr.h"#include "mp3_hdr.h"#include "liba52/a52.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 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 8static char ftypes[] = {'?', 'I', 'P', 'B'}; #define FTYPE(x) (ftypes[(x)])#define MAX_PATTERN_LENGTH 2000000static unsigned char bff_mask[MAX_PATTERN_LENGTH];	//2 million frames are enoughstatic 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, 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;#undef memcpy#define memcpy uc_memcpyenum 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;	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;} muxer_priv_t;typedef struct {	int has_pts, has_dts, pes_is_aligned, type, min_pes_hlen, psm_fixed;	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 3m_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.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 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 = (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].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 = (muxer_stream_t*) 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 = (muxer_headers_t*) 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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?