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 + -
显示快捷键?