demux_real.c

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

C
1,820
字号
/*    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 <mplaylib.h>#include <inttypes.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "stream/stream.h"#include "demuxer.h"#include "stheader.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 SEEK_ABSOLUTE (1 << 0)#define SEEK_FACTOR   (1 << 1)//#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))#undef memcpy#define memcpy uc_memcpy#define MAX_STREAMS 32//#undef F(x,s...)//#define F(x,s...)static 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    */    unsigned int intl_id[MAX_STREAMS]; ///< interleaver id, per stream    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;//! 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 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);	//F("offset = %d %d",i,priv->index_table[stream_id][i].offset);	stream_skip(demuxer->stream, 4); /* packetno *///priv->index_table[stream_id][i].packetno = stream_read_dword(demuxer->stream);	//unsigned int packetno = stream_read_dword(demuxer->stream);		//printf("Index table: Stream#%d: entry: %d: pos: %d :timestamp: %d packetno: %d\n",	//    stream_id, i, priv->index_table[stream_id][i].offset,priv->index_table[stream_id][i].timestamp,packetno);    }        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);  }  for (i = 0; i < MAX_STREAMS; i++)  {    if (priv->index_table_size[i] > 0)    {      dump_index(demuxer, i);    }

⌨️ 快捷键说明

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