📄 av_parsers.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / Media Tools sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/media_dev.h>#include <gpac/internal/ogg.h>#include <gpac/constants.h>#include <gpac/math.h>/* MPEG-4 video (14496-2)*/#define M4V_VO_START_CODE 0x00#define M4V_VOL_START_CODE 0x20#define M4V_VOP_START_CODE 0xB6#define M4V_VISOBJ_START_CODE 0xB5#define M4V_VOS_START_CODE 0xB0#define M4V_GOV_START_CODE 0xB3#define M4V_UDTA_START_CODE 0xB2#define M2V_PIC_START_CODE 0x00#define M2V_SEQ_START_CODE 0xB3#define M2V_EXT_START_CODE 0xB5#define M2V_GOP_START_CODE 0xB8struct __tag_m4v_parser{ GF_BitStream *bs; Bool mpeg12; u32 current_object_type; u32 current_object_start; u32 tc_dec, prev_tc_dec, tc_disp, prev_tc_disp;};GF_EXPORTGF_M4VParser *gf_m4v_parser_new(char *data, u32 data_size, Bool mpeg12video){ GF_M4VParser *tmp; if (!data || !data_size) return NULL; GF_SAFEALLOC(tmp, GF_M4VParser); tmp->bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ); tmp->mpeg12 = mpeg12video; return tmp;}GF_M4VParser *gf_m4v_parser_bs_new(GF_BitStream *bs, Bool mpeg12video){ GF_M4VParser *tmp; GF_SAFEALLOC(tmp, GF_M4VParser); tmp->bs = bs; tmp->mpeg12 = mpeg12video; return tmp;}GF_EXPORTvoid gf_m4v_parser_del(GF_M4VParser *m4v){ gf_bs_del(m4v->bs); free(m4v);}#define M4V_CACHE_SIZE 4096s32 M4V_LoadObject(GF_M4VParser *m4v){ u32 v, bpos, found; char m4v_cache[M4V_CACHE_SIZE]; u64 end, cache_start, load_size; if (!m4v) return 0; bpos = 0; found = 0; load_size = 0; end = 0; cache_start = 0; v = 0xffffffff; while (!end) { /*refill cache*/ if (bpos == (u32) load_size) { if (!gf_bs_available(m4v->bs)) break; load_size = gf_bs_available(m4v->bs); if (load_size>M4V_CACHE_SIZE) load_size=M4V_CACHE_SIZE; bpos = 0; cache_start = gf_bs_get_position(m4v->bs); gf_bs_read_data(m4v->bs, m4v_cache, (u32) load_size); } v = ( (v<<8) & 0xFFFFFF00) | ((u8) m4v_cache[bpos]); bpos++; if ((v & 0xFFFFFF00) == 0x00000100) { end = cache_start+bpos-4; found = 1; break; } } if (!found) return -1; m4v->current_object_start = (u32) end; gf_bs_seek(m4v->bs, end+3); m4v->current_object_type = gf_bs_read_u8(m4v->bs); return (s32) m4v->current_object_type;}GF_EXPORTconst char *gf_m4v_get_profile_name(u8 video_pl){ switch (video_pl) { case 0x00: return "Reserved (0x00) Profile"; case 0x01: return "Simple Profile @ Level 1"; case 0x02: return "Simple Profile @ Level 2"; case 0x03: return "Simple Profile @ Level 3"; case 0x08: return "Simple Profile @ Level 0"; case 0x10: return "Simple Scalable Profile @ Level 0"; case 0x11: return "Simple Scalable Profile @ Level 1"; case 0x12: return "Simple Scalable Profile @ Level 2"; case 0x15: return "AVC/H264 Profile"; case 0x21: return "Core Profile @ Level 1"; case 0x22: return "Core Profile @ Level 2"; case 0x32: return "Main Profile @ Level 2"; case 0x33: return "Main Profile @ Level 3"; case 0x34: return "Main Profile @ Level 4"; case 0x42: return "N-bit Profile @ Level 2"; case 0x51: return "Scalable Texture Profile @ Level 1"; case 0x61: return "Simple Face Animation Profile @ Level 1"; case 0x62: return "Simple Face Animation Profile @ Level 2"; case 0x63: return "Simple FBA Profile @ Level 1"; case 0x64: return "Simple FBA Profile @ Level 2"; case 0x71: return "Basic Animated Texture Profile @ Level 1"; case 0x72: return "Basic Animated Texture Profile @ Level 2"; case 0x81: return "Hybrid Profile @ Level 1"; case 0x82: return "Hybrid Profile @ Level 2"; case 0x91: return "Advanced Real Time Simple Profile @ Level 1"; case 0x92: return "Advanced Real Time Simple Profile @ Level 2"; case 0x93: return "Advanced Real Time Simple Profile @ Level 3"; case 0x94: return "Advanced Real Time Simple Profile @ Level 4"; case 0xA1: return "Core Scalable Profile @ Level1"; case 0xA2: return "Core Scalable Profile @ Level2"; case 0xA3: return "Core Scalable Profile @ Level3"; case 0xB1: return "Advanced Coding Efficiency Profile @ Level 1"; case 0xB2: return "Advanced Coding Efficiency Profile @ Level 2"; case 0xB3: return "Advanced Coding Efficiency Profile @ Level 3"; case 0xB4: return "Advanced Coding Efficiency Profile @ Level 4"; case 0xC1: return "Advanced Core Profile @ Level 1"; case 0xC2: return "Advanced Core Profile @ Level 2"; case 0xD1: return "Advanced Scalable Texture @ Level1"; case 0xD2: return "Advanced Scalable Texture @ Level2"; case 0xE1: return "Simple Studio Profile @ Level 1"; case 0xE2: return "Simple Studio Profile @ Level 2"; case 0xE3: return "Simple Studio Profile @ Level 3"; case 0xE4: return "Simple Studio Profile @ Level 4"; case 0xE5: return "Core Studio Profile @ Level 1"; case 0xE6: return "Core Studio Profile @ Level 2"; case 0xE7: return "Core Studio Profile @ Level 3"; case 0xE8: return "Core Studio Profile @ Level 4"; case 0xF0: return "Advanced Simple Profile @ Level 0"; case 0xF1: return "Advanced Simple Profile @ Level 1"; case 0xF2: return "Advanced Simple Profile @ Level 2"; case 0xF3: return "Advanced Simple Profile @ Level 3"; case 0xF4: return "Advanced Simple Profile @ Level 4"; case 0xF5: return "Advanced Simple Profile @ Level 5"; case 0xF7: return "Advanced Simple Profile @ Level 3b"; case 0xF8: return "Fine Granularity Scalable Profile @ Level 0"; case 0xF9: return "Fine Granularity Scalable Profile @ Level 1"; case 0xFA: return "Fine Granularity Scalable Profile @ Level 2"; case 0xFB: return "Fine Granularity Scalable Profile @ Level 3"; case 0xFC: return "Fine Granularity Scalable Profile @ Level 4"; case 0xFD: return "Fine Granularity Scalable Profile @ Level 5"; case 0xFE: return "Not part of MPEG-4 Visual profiles"; case 0xFF: return "No visual capability required"; default: return "ISO Reserved Profile"; }}GF_EXPORTvoid gf_m4v_rewrite_pl(char **o_data, u32 *o_dataLen, u8 PL){ u32 pos = 0; unsigned char *data = (unsigned char *)*o_data; u32 dataLen = *o_dataLen; while (pos+4<dataLen) { if (!data[pos] && !data[pos+1] && (data[pos+2]==0x01) && (data[pos+3]==M4V_VOS_START_CODE)) { data[pos+4] = PL; return; } pos ++; } /*emulate VOS at beggining*/ (*o_data) = (char *)malloc(sizeof(char)*(dataLen+5)); (*o_data)[0] = 0; (*o_data)[1] = 0; (*o_data)[2] = 1; (*o_data)[3] = (char) M4V_VOS_START_CODE; (*o_data)[4] = PL; memcpy( (*o_data + 5), data, sizeof(char)*dataLen); free(data); (*o_dataLen) = dataLen + 5;}static GF_Err M4V_Reset(GF_M4VParser *m4v, u32 start){ gf_bs_seek(m4v->bs, start); m4v->current_object_start = start; m4v->current_object_type = 0; return GF_OK;}static GF_Err gf_m4v_parse_config_mpeg12(GF_M4VParser *m4v, GF_M4VDecSpecInfo *dsi){ char p[4]; s32 o_type; u8 go, par; if (!m4v || !dsi) return GF_BAD_PARAM; memset(dsi, 0, sizeof(GF_M4VDecSpecInfo)); dsi->VideoPL = 0; go = 1; while (go) { o_type = M4V_LoadObject(m4v); switch (o_type) { case M2V_SEQ_START_CODE: dsi->RAP_stream = 1; gf_bs_read_data(m4v->bs, p, 4); dsi->width = (p[0] << 4) | ((p[1] >> 4) & 0xf); dsi->height = ((p[1] & 0xf) << 8) | p[2]; dsi->VideoPL = 0x6A; par = (p[3] >> 4) & 0xf; switch (par) { case 2: dsi->par_num = 4; dsi->par_den = 3; break; case 3: dsi->par_num = 16; dsi->par_den = 9; break; case 4: dsi->par_num = 2; dsi->par_den = 21; break; default: dsi->par_den = dsi->par_num = 0; break; } switch (p[3] & 0xf) { case 0: break; case 1: dsi->fps = 24000.0/1001.0; break; case 2: dsi->fps = 24.0; break; case 3: dsi->fps = 25.0; break; case 4: dsi->fps = 30000.0/1001.0; break; case 5: dsi->fps = 30.0; break; case 6: dsi->fps = 50.0; break; case 7: dsi->fps = ((60.0*1000.0)/1001.0); break; case 8: dsi->fps = 60.0; break; case 9: dsi->fps = 1; break; case 10: dsi->fps = 5; break; case 11: dsi->fps = 10; break; case 12: dsi->fps = 12; break; case 13: dsi->fps = 15; break; } break; case M2V_EXT_START_CODE: gf_bs_read_data(m4v->bs, p, 4); if ( ((p[0] >> 4) & 0xf) == 1) { dsi->VideoPL = 0x65; dsi->height = ((p[1] & 0x1) << 13) | ((p[2] & 0x80) << 5) | (dsi->height & 0x0fff); dsi->width = (((p[2] >> 5) & 0x3) << 12) | (dsi->width & 0x0fff); } break; case M2V_PIC_START_CODE: go = 0; break; default: break; /*EOS*/ case -1: go = 0; m4v->current_object_start = (u32) gf_bs_get_position(m4v->bs); break; } } M4V_Reset(m4v, 0); return GF_OK;}static const struct { u32 w, h; } m4v_sar[6] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 } };static u8 m4v_get_sar_idx(u32 w, u32 h){ u32 i; for (i=0; i<6; i++) { if ((m4v_sar[i].w==w) && (m4v_sar[i].h==h)) return i; } return 0xF;}static GF_Err gf_m4v_parse_config_mpeg4(GF_M4VParser *m4v, GF_M4VDecSpecInfo *dsi){ s32 o_type; u8 go, verid, par; s32 clock_rate; if (!m4v || !dsi) return GF_BAD_PARAM; memset(dsi, 0, sizeof(GF_M4VDecSpecInfo)); go = 1; while (go) { o_type = M4V_LoadObject(m4v); switch (o_type) { /*vosh*/ case M4V_VOS_START_CODE: dsi->VideoPL = (u8) gf_bs_read_u8(m4v->bs); break; case M4V_VOL_START_CODE: verid = 0; dsi->RAP_stream = gf_bs_read_int(m4v->bs, 1); dsi->objectType = gf_bs_read_int(m4v->bs, 8); if (gf_bs_read_int(m4v->bs, 1)) { verid = gf_bs_read_int(m4v->bs, 4); gf_bs_read_int(m4v->bs, 3); } par = gf_bs_read_int(m4v->bs, 4); if (par == 0xF) { dsi->par_num = gf_bs_read_int(m4v->bs, 8); dsi->par_den = gf_bs_read_int(m4v->bs, 8); } else if (par<6) { dsi->par_num = m4v_sar[par].w; dsi->par_den = m4v_sar[par].h; } if (gf_bs_read_int(m4v->bs, 1)) { gf_bs_read_int(m4v->bs, 3); if (gf_bs_read_int(m4v->bs, 1)) gf_bs_read_int(m4v->bs, 79); } dsi->has_shape = gf_bs_read_int(m4v->bs, 2); if (dsi->has_shape && (verid!=1) ) gf_bs_read_int(m4v->bs, 4); gf_bs_read_int(m4v->bs, 1); /*clock rate*/ dsi->clock_rate = gf_bs_read_int(m4v->bs, 16); /*marker*/ gf_bs_read_int(m4v->bs, 1); clock_rate = dsi->clock_rate-1; if (clock_rate >= 65536) clock_rate = 65535; if (clock_rate > 0) { for (dsi->NumBitsTimeIncrement = 1; dsi->NumBitsTimeIncrement < 16; dsi->NumBitsTimeIncrement++) { if (clock_rate == 1) break; clock_rate = (clock_rate >> 1); } } else { /*fix from vivien for divX*/ dsi->NumBitsTimeIncrement = 1; } /*fixed FPS stream*/ dsi->time_increment = 0; if (gf_bs_read_int(m4v->bs, 1)) { dsi->time_increment = gf_bs_read_int(m4v->bs, dsi->NumBitsTimeIncrement); } if (!dsi->has_shape) { gf_bs_read_int(m4v->bs, 1); dsi->width = gf_bs_read_int(m4v->bs, 13); gf_bs_read_int(m4v->bs, 1); dsi->height = gf_bs_read_int(m4v->bs, 13); } else { dsi->width = dsi->height = 0; } /*shape will be done later*/ gf_bs_align(m4v->bs); break; case M4V_VOP_START_CODE: case M4V_GOV_START_CODE: go = 0; break; /*EOS*/ case -1: go = 0; m4v->current_object_start = (u32) gf_bs_get_position(m4v->bs); break; /*don't interest us*/ case M4V_UDTA_START_CODE: default: break; } } return GF_OK;}GF_EXPORTGF_Err gf_m4v_parse_config(GF_M4VParser *m4v, GF_M4VDecSpecInfo *dsi){ if (m4v->mpeg12) { return gf_m4v_parse_config_mpeg12(m4v, dsi); } else { return gf_m4v_parse_config_mpeg4(m4v, dsi); }}static GF_Err gf_m4v_parse_frame_mpeg12(GF_M4VParser *m4v, GF_M4VDecSpecInfo dsi, u8 *frame_type, u32 *time_inc, u32 *size, u32 *start, Bool *is_coded){ u8 go, hasVOP, firstObj, val; s32 o_type; if (!m4v || !size || !start || !frame_type) return GF_BAD_PARAM; *size = 0; firstObj = 1; hasVOP = 0; *is_coded = 0; m4v->current_object_type = (u32) -1; *frame_type = 0; M4V_Reset(m4v, m4v->current_object_start); go = 1; while (go) { o_type = M4V_LoadObject(m4v); switch (o_type) { case M2V_PIC_START_CODE: /*done*/ if (hasVOP) { go = 0; break; } if (firstObj) { *start = m4v->current_object_start; firstObj = 0; } hasVOP = 1; *is_coded = 1; val = gf_bs_read_u8(m4v->bs); val = gf_bs_read_u8(m4v->bs); *frame_type = ( (val >> 3) & 0x7 ) - 1; break; case M2V_GOP_START_CODE: if (firstObj) { *start = m4v->current_object_start; firstObj = 0; } if (hasVOP) go = 0; break; case M2V_SEQ_START_CODE: if (firstObj) { *start = m4v->current_object_start; firstObj = 0; } if (hasVOP) { go = 0; break; } /**/ break; default: break; case -1: *size = (u32) gf_bs_get_position(m4v->bs) - *start; return GF_EOS; } } *size = m4v->current_object_start - *start; return GF_OK;}static GF_Err gf_m4v_parse_frame_mpeg4(GF_M4VParser *m4v, GF_M4VDecSpecInfo dsi, u8 *frame_type, u32 *time_inc, u32 *size, u32 *start, Bool *is_coded){ u8 go, hasVOP, firstObj, secs; s32 o_type; u32 vop_inc = 0; if (!m4v || !size || !start || !frame_type) return GF_BAD_PARAM; *size = 0; firstObj = 1; hasVOP = 0; *is_coded = 0; m4v->current_object_type = (u32) -1; *frame_type = 0; M4V_Reset(m4v, m4v->current_object_start); go = 1; while (go) { o_type = M4V_LoadObject(m4v); switch (o_type) { case M4V_VOP_START_CODE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -