demux_real_new.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,849 行 · 第 1/5 页
C
1,849 行
/* Real parser & demuxer (C) Alex Beregszaszi (C) 2005, 2006 Roberto Togni Based on FFmpeg's libav/rm.c.Audio codecs: (supported by RealPlayer8 for Linux) DNET - RealAudio 3.0, really it's AC3 in swapped-byteorder SIPR - SiproLab's audio codec, ACELP decoder working with MPlayer, needs fine-tuning too :) ATRC - RealAudio 8 (ATRAC3) - www.minidisc.org/atrac3_article.pdf, ACM decoder uploaded, needs some fine-tuning to work -> RealAudio 8 COOK/COKR - Real Cooker -> RealAudio G2Video codecs: (supported by RealPlayer8 for Linux) RV10 - H.263 based, working with libavcodec's decoder RV20-RV40 - using RealPlayer's codec plugins*/#include <mplaylib.h>#include "mplaylib.h"#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "stream.h"#include "demuxer.h"#include "stheader.h"#include "bswap.h"#ifdef USE_LIBAVCODEC_SO#include <ffmpeg/avcodec.h>#elif defined(USE_LIBAVCODEC)#include "libavcodec/avcodec.h"#else#define FF_INPUT_BUFFER_PADDING_SIZE 8#endif//#define mp_dbg(mod,lev, args... ) mp_msg_c((mod<<8)|lev, ## args )#define MKTAG(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24))#define MAX_STREAMS 32static unsigned char sipr_swaps[38][2]={ {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68}, {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46}, {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56}, {42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83}, {77,80} };typedef struct { unsigned int timestamp; int offset;// int packetno;// int len; /* only filled by our index generator */// int flags; /* only filled by our index generator */} real_index_table_t;typedef struct { /* for seeking */ int index_chunk_offset; real_index_table_t *index_table[MAX_STREAMS]; // int *index_table[MAX_STREAMS]; int index_table_size[MAX_STREAMS]; int index_malloc_size[MAX_STREAMS]; int data_chunk_offset; int num_of_packets; int current_packet; // need for seek int audio_need_keyframe; int video_after_seek; int current_apacket; int current_vpacket; // timestamp correction: int64_t kf_base;// timestamp of the prev. video keyframe unsigned int kf_pts; // timestamp of next video keyframe unsigned int a_pts; // previous audio timestamp double v_pts; // previous video timestamp unsigned long duration; /* stream id table */// int last_a_stream;// int a_streams[MAX_STREAMS];// int last_v_stream;// int v_streams[MAX_STREAMS]; /** * Used to demux multirate files */ int is_multirate; ///< != 0 for multirate files int str_data_offset[MAX_STREAMS]; ///< Data chunk offset for every audio/video stream int audio_curpos; ///< Current file position for audio demuxing int video_curpos; ///< Current file position for video demuxing int a_num_of_packets; ///< Number of audio packets int v_num_of_packets; ///< Number of video packets int a_idx_ptr; ///< Audio index position pointer int v_idx_ptr; ///< Video index position pointer int a_bitrate; ///< Audio bitrate int v_bitrate; ///< Video bitrate int stream_switch; ///< Flag used to switch audio/video demuxing /** * Used to reorder audio data */ int sub_packet_size[MAX_STREAMS]; ///< sub packet size, per stream int sub_packet_h[MAX_STREAMS]; ///< number of coded frames per block int coded_framesize[MAX_STREAMS]; ///< coded frame size, per stream int audiopk_size[MAX_STREAMS]; ///< audio packet size unsigned char *audio_buf; ///< place to store reordered audio data double *audio_timestamp; ///< timestamp for each audio packet int sub_packet_cnt; ///< number of subpacket already received int audio_filepos; ///< file position of first audio packet in block } real_priv_t;rm_parser* pParser = HXNULL; //! use at most 200 MB of memory for index, corresponds to around 25 million entries#define MAX_INDEX_ENTRIES (200*1024*1024 / sizeof(real_index_table_t))/* originally from FFmpeg */static void get_str(int isbyte, demuxer_t *demuxer, char *buf, int buf_size){ int len; if (isbyte) len = stream_read_char(demuxer->stream); else len = stream_read_word(demuxer->stream); stream_read(demuxer->stream, buf, (len > buf_size) ? buf_size : len); if (len > buf_size) stream_skip(demuxer->stream, len-buf_size); mp_msg(MSGT_DEMUX, MSGL_V, "read_str: %d bytes read\n", len);}static void skip_str(int isbyte, demuxer_t *demuxer){ int len; if (isbyte) len = stream_read_char(demuxer->stream); else len = stream_read_word(demuxer->stream); stream_skip(demuxer->stream, len); mp_msg(MSGT_DEMUX, MSGL_V, "skip_str: %d bytes skipped\n", len);}static void dump_index(demuxer_t *demuxer, int stream_id){ real_priv_t *priv = demuxer->priv; real_index_table_t *index; int i, entries; if ( mp_msg_test(MSGT_DEMUX,MSGL_V) ) return; if ((unsigned)stream_id >= MAX_STREAMS) return; index = priv->index_table[stream_id]; entries = priv->index_table_size[stream_id]; mp_msg(MSGT_DEMUX, MSGL_V, "Index table for stream %d\n", stream_id); for (i = 0; i < entries; i++) {#if 1 mp_msg(MSGT_DEMUX, MSGL_V,"i: %d, pos: %d, timestamp: %u\n", i, index[i].offset, index[i].timestamp);#else mp_msg(MSGT_DEMUX, MSGL_V,"packetno: %x pos: %x len: %x timestamp: %x flags: %x\n", index[i].packetno, index[i].offset, index[i].len, index[i].timestamp, index[i].flags);#endif }}static int parse_index_chunk(demuxer_t *demuxer){ real_priv_t *priv = demuxer->priv; int origpos = stream_tell(demuxer->stream); int next_header_pos = priv->index_chunk_offset; int i, entries, stream_id;read_index: stream_seek(demuxer->stream, next_header_pos); i = stream_read_dword_le(demuxer->stream); if ((i == -256) || (i != MKTAG('I', 'N', 'D', 'X'))) { mp_msg(MSGT_DEMUX, MSGL_WARN,"Something went wrong, no index chunk found on given address (%d)\n", next_header_pos); index_mode = -1; if (i == -256) stream_reset(demuxer->stream); stream_seek(demuxer->stream, origpos); return 0; //goto end; } mp_msg(MSGT_DEMUX, MSGL_V,"Reading index table from index chunk (%d)\n", next_header_pos); i = stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX, MSGL_V,"size: %d bytes\n", i); i = stream_read_word(demuxer->stream); if (i != 0) mp_msg(MSGT_DEMUX, MSGL_WARN,"Hmm, index table with unknown version (%d), please report it to MPlayer developers!\n", i); entries = stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX, MSGL_V,"entries: %d\n", entries); stream_id = stream_read_word(demuxer->stream); mp_msg(MSGT_DEMUX, MSGL_V,"stream_id: %d\n", stream_id); next_header_pos = stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX, MSGL_V,"next_header_pos: %d\n", next_header_pos); if (entries <= 0 || entries > MAX_INDEX_ENTRIES) { if (next_header_pos) goto read_index; i = entries; goto end; } priv->index_table_size[stream_id] = entries; priv->index_table[stream_id] = calloc(priv->index_table_size[stream_id], sizeof(real_index_table_t)); for (i = 0; i < entries; i++) { stream_skip(demuxer->stream, 2); /* version */ priv->index_table[stream_id][i].timestamp = stream_read_dword(demuxer->stream); priv->index_table[stream_id][i].offset = stream_read_dword(demuxer->stream); stream_skip(demuxer->stream, 4); /* packetno */// priv->index_table[stream_id][i].packetno = stream_read_dword(demuxer->stream);// printf("Index table: Stream#%d: entry: %d: pos: %d\n",// stream_id, i, priv->index_table[stream_id][i].offset); } dump_index(demuxer, stream_id); if (next_header_pos > 0) goto read_index;end: if (i == -256) stream_reset(demuxer->stream); stream_seek(demuxer->stream, origpos); if (i == -256) return 0; else return 1;}#if 1static void add_index_item(demuxer_t *demuxer, int stream_id, unsigned int timestamp, int offset){ if ((unsigned)stream_id < MAX_STREAMS) { real_priv_t *priv = demuxer->priv; real_index_table_t *index; if (priv->index_table_size[stream_id] >= MAX_INDEX_ENTRIES) { mp_msg(MSGT_DEMUXER, MSGL_WARN, "Index too large during building\n"); return; } if (priv->index_table_size[stream_id] >= priv->index_malloc_size[stream_id]) { if (priv->index_malloc_size[stream_id] == 0) priv->index_malloc_size[stream_id] = 2048; else priv->index_malloc_size[stream_id] += priv->index_malloc_size[stream_id] / 2; // in case we have a really large chunk... if (priv->index_table_size[stream_id] >= priv->index_malloc_size[stream_id]) priv->index_malloc_size[stream_id] = priv->index_table_size[stream_id] + 1; priv->index_table[stream_id] = realloc(priv->index_table[stream_id], priv->index_malloc_size[stream_id]*sizeof(priv->index_table[0][0])); } if (priv->index_table_size[stream_id] > 0) { index = &priv->index_table[stream_id][priv->index_table_size[stream_id] - 1]; if (index->timestamp >= timestamp || index->offset >= offset) return; } index = &priv->index_table[stream_id][priv->index_table_size[stream_id]++]; index->timestamp = timestamp; index->offset = offset; }}static void add_index_segment(demuxer_t *demuxer, int seek_stream_id, int64_t seek_timestamp){ int tag, len, stream_id, flags; unsigned int timestamp; if (seek_timestamp != -1 && (unsigned)seek_stream_id >= MAX_STREAMS) return; while (1) { demuxer->filepos = stream_tell(demuxer->stream); tag = stream_read_dword(demuxer->stream); if (tag == MKTAG('A', 'T', 'A', 'D')) { stream_skip(demuxer->stream, 14); continue; /* skip to next loop */ } len = tag & 0xffff; if (tag == -256 || len < 12) break; stream_id = stream_read_word(demuxer->stream); timestamp = stream_read_dword(demuxer->stream); stream_skip(demuxer->stream, 1); /* reserved */ flags = stream_read_char(demuxer->stream); if (flags == -256) break; if (flags & 2) { add_index_item(demuxer, stream_id, timestamp, demuxer->filepos); if (stream_id == seek_stream_id && timestamp >= seek_timestamp) { stream_seek(demuxer->stream, demuxer->filepos); return; } } // printf("Index: stream=%d packet=%d timestamp=%u len=%d flags=0x%x datapos=0x%x\n", stream_id, entries, timestamp, len, flags, index->offset); /* skip data */ stream_skip(demuxer->stream, len-12); }}static int generate_index(demuxer_t *demuxer){ real_priv_t *priv = demuxer->priv; int origpos = stream_tell(demuxer->stream); int data_pos = priv->data_chunk_offset-10; int i; int tag; stream_seek(demuxer->stream, data_pos); tag = stream_read_dword(demuxer->stream); if (tag != MKTAG('A', 'T', 'A', 'D')) { mp_msg(MSGT_DEMUX, MSGL_WARN,"Something went wrong, no data chunk found on given address (%d)\n", data_pos); } else { stream_skip(demuxer->stream, 14); add_index_segment(demuxer, -1, -1); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?