⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demux_real.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    Real parser & demuxer        (C) Alex Beregszaszi        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 <stdio.h>#include <stdlib.h>#include <unistd.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "stream.h"#include "demuxer.h"#include "stheader.h"#include "bswap.h"//#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 32typedef struct {    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:    int		kf_base;// timestamp of the prev. video keyframe    int		kf_pts;	// timestamp of next video keyframe    int		a_pts;	// previous audio timestamp    float	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} real_priv_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 (verbose<=1)	return;        if (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: %d\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)    {	if (next_header_pos)	    goto read_index;	i = entries;	goto end;    }    priv->index_table_size[stream_id] = entries;    priv->index_table[stream_id] = malloc(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, 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] >= 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, int seek_timestamp){  int tag, len, stream_id, timestamp, flags;  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=%d 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);    }  }  stream_reset(demuxer->stream);  stream_seek(demuxer->stream, origpos);  return 0;}#elsestatic 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 num_of_packets = 0;    int i, entries = 0;    int len, stream_id = 0, timestamp, flags;    int tab_pos = 0;read_index:    stream_seek(demuxer->stream, data_pos);    i = stream_read_dword_le(demuxer->stream);    if ((i == -256) || (i != MKTAG('D', 'A', 'T', 'A')))    {	mp_msg(MSGT_DEMUX, MSGL_WARN,"Something went wrong, no data chunk found on given address (%d)\n",	    data_pos);	goto end;    }    stream_skip(demuxer->stream, 4); /* chunk size */    stream_skip(demuxer->stream, 2); /* version */        num_of_packets = stream_read_dword(demuxer->stream);    mp_msg(MSGT_DEMUX, MSGL_V,"Generating index table from raw data (pos: 0x%x) for %d packets\n",	data_pos, num_of_packets);    data_pos = stream_read_dword_le(demuxer->stream)-10; /* next data chunk */    for (i = 0; i < MAX_STREAMS; i++)    {    priv->index_table_size[i] = num_of_packets;    priv->index_table[i] = malloc(priv->index_table_size[i] * sizeof(real_index_table_t));

⌨️ 快捷键说明

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