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

📄 demux_ogg.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 4 页
字号:
#include "config.h"#ifdef HAVE_OGGVORBIS#include <stdlib.h>#include <stdio.h>#include <string.h>#include <assert.h>#include <math.h>#include "../mp_msg.h"#include "../help_mp.h"#include "stream.h"#include "demuxer.h"#include "stheader.h"#define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')#define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')#ifdef TREMOR#include <tremor/ogg.h>#include <tremor/ivorbiscodec.h>#else#include <ogg/ogg.h>#include <vorbis/codec.h>#endif#ifdef HAVE_OGGTHEORA#include <theora/theora.h>#endif#define BLOCK_SIZE 4096/// Vorbis decoder context : we need the vorbis_info for vorbis timestamping/// Shall we put this struct def in a common header ?typedef struct ov_struct_st {  vorbis_info      vi; /* struct that stores all the static vorbis bitstream			  settings */  vorbis_comment   vc; /* struct that stores all the bitstream user comments */  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */  vorbis_block     vb; /* local working space for packet->PCM decode */  float            rg_scale; /* replaygain scale */#ifdef TREMOR  int              rg_scale_int;#endif} ov_struct_t;/* Theora decoder context : we won't be able to interpret granule positions * without using theora_granule_time with the theora_state of the stream. * This is duplicated in `vd_theora.c'; put this in a common header? */#ifdef HAVE_OGGTHEORAtypedef struct theora_struct_st {    theora_state st;    theora_comment cc;    theora_info inf;} theora_struct_t;#endif//// OggDS headers// Header for the new header formattypedef struct stream_header_video{	ogg_int32_t	width;	ogg_int32_t	height;} stream_header_video;	typedef struct stream_header_audio{	ogg_int16_t	channels;	ogg_int16_t	blockalign;	ogg_int32_t	avgbytespersec;} stream_header_audio;typedef struct __attribute__((__packed__)) stream_header{	char	streamtype[8];	char	subtype[4];	ogg_int32_t	size;				// size of the structure	ogg_int64_t	time_unit;			// in reference time	ogg_int64_t	samples_per_unit;	ogg_int32_t default_len;		// in media time	ogg_int32_t buffersize;	ogg_int16_t	bits_per_sample;	ogg_int16_t padding;	union	{		// Video specific		stream_header_video	video;		// Audio specific		stream_header_audio	audio;	} sh;} stream_header;/// Our private datastypedef struct ogg_syncpoint {  int64_t granulepos;  off_t page_pos;} ogg_syncpoint_t;/// A logical streamtypedef struct ogg_stream {  /// Timestamping stuff  float samplerate; /// granulpos 2 time  int64_t lastpos;  int32_t lastsize;  // Logical stream state  ogg_stream_state stream;  int hdr_packets;  int vorbis;  int theora;  int flac;  int text;  int id;} ogg_stream_t;typedef struct ogg_demuxer {  /// Physical stream state  ogg_sync_state sync;  /// Current page  ogg_page page;  /// Logical streams  ogg_stream_t *subs;  int num_sub;  ogg_syncpoint_t* syncpoints;  int num_syncpoint;  off_t pos, last_size;  int64_t final_granulepos;  /* Used for subtitle switching. */  int n_text;  int *text_ids;  char **text_langs;} ogg_demuxer_t;#define NUM_VORBIS_HDR_PACKETS 3/// Some defines from OggDS#define PACKET_TYPE_HEADER   0x01#define PACKET_TYPE_BITS         0x07#define PACKET_LEN_BITS01       0xc0#define PACKET_LEN_BITS2         0x02#define PACKET_IS_SYNCPOINT  0x08extern int index_mode;extern char *dvdsub_lang, *audio_lang;extern int dvdsub_id;extern int demux_aid_vid_mismatch;//-------- subtitle support - should be moved to decoder layer, and queue//                          - subtitles up in demuxer buffer...#include "../subreader.h"#include "../libvo/sub.h"#define OGG_SUB_MAX_LINE 128static subtitle ogg_sub;extern subtitle* vo_sub;static float clear_sub;//FILE* subout;staticuint16_t get_uint16 (const void *buf){  uint16_t      ret;  unsigned char *tmp;  tmp = (unsigned char *) buf;  ret = tmp[1] & 0xff;  ret = (ret << 8) + (tmp[0] & 0xff);  return (ret);}staticuint32_t get_uint32 (const void *buf){  uint32_t      ret;  unsigned char *tmp;  tmp = (unsigned char *) buf;  ret = tmp[3] & 0xff;  ret = (ret << 8) + (tmp[2] & 0xff);  ret = (ret << 8) + (tmp[1] & 0xff);  ret = (ret << 8) + (tmp[0] & 0xff);  return (ret);}staticuint64_t get_uint64 (const void *buf){  uint64_t      ret;  unsigned char *tmp;  tmp = (unsigned char *) buf;  ret = tmp[7] & 0xff;  ret = (ret << 8) + (tmp[6] & 0xff);  ret = (ret << 8) + (tmp[5] & 0xff);  ret = (ret << 8) + (tmp[4] & 0xff);  ret = (ret << 8) + (tmp[3] & 0xff);  ret = (ret << 8) + (tmp[2] & 0xff);  ret = (ret << 8) + (tmp[1] & 0xff);  ret = (ret << 8) + (tmp[0] & 0xff);  return (ret);}void demux_ogg_init_sub () {  int lcv;  if(!ogg_sub.text[0]) // not yet allocated  for (lcv = 0; lcv < SUB_MAX_TEXT; lcv++) {    ogg_sub.text[lcv] = (char*)malloc(OGG_SUB_MAX_LINE);  }}void demux_ogg_add_sub (ogg_stream_t* os,ogg_packet* pack) {  int lcv;  int line_pos = 0;  int ignoring = 0;  char *packet = pack->packet;  mp_msg(MSGT_DEMUX,MSGL_DBG2,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",      (unsigned char)packet[0],      (unsigned char)packet[1],      (unsigned char)packet[2],      &packet[3]);  ogg_sub.lines = 0;  if (((unsigned char)packet[0]) == 0x88) { // some subtitle text    // Find data start    int32_t duration = 0;    int16_t hdrlen = (*packet & PACKET_LEN_BITS01)>>6, i;    hdrlen |= (*packet & PACKET_LEN_BITS2) <<1;    lcv = 1 + hdrlen;    for (i = hdrlen; i > 0; i--) {      duration <<= 8;      duration |= (unsigned char)packet[i];    }    if ((hdrlen > 0) && (duration > 0)) {      float pts;      if(pack->granulepos == -1)        pack->granulepos = os->lastpos + os->lastsize;      pts = (float)pack->granulepos/(float)os->samplerate;      clear_sub = 1.0 + pts + (float)duration/1000.0;    }    while (1) {      int c = packet[lcv++];      if(c=='\n' || c==0 || line_pos >= OGG_SUB_MAX_LINE-1){	  ogg_sub.text[ogg_sub.lines][line_pos] = 0; // close sub          if(line_pos) ogg_sub.lines++;	  if(!c || ogg_sub.lines>=SUB_MAX_TEXT) break; // EOL or TooMany          line_pos = 0;      }      switch (c) {        case '\r':        case '\n': // just ignore linefeeds for now                   // their placement seems rather haphazard          break;        case '<': // some html markup, ignore for now          ignoring = 1;          break;        case '>':          ignoring = 0;          break;        default:          if(!ignoring) 	  ogg_sub.text[ogg_sub.lines][line_pos++] = c;          break;      }    }  }  mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg sub lines: %d  first: '%s'\n",      ogg_sub.lines, ogg_sub.text[0]);#ifdef USE_ICONV  subcp_recode1(&ogg_sub);#endif  vo_sub = &ogg_sub;  vo_osd_changed(OSDTYPE_SUBTITLE);}// get the logical stream of the current page// fill os if non NULL and return the stream idstatic  int demux_ogg_get_page_stream(ogg_demuxer_t* ogg_d,ogg_stream_state** os) {  int id,s_no;  ogg_page* page = &ogg_d->page;  s_no = ogg_page_serialno(page);  for(id= 0; id < ogg_d->num_sub ; id++) {    if(s_no == ogg_d->subs[id].stream.serialno)      break;  }  if(id == ogg_d->num_sub) {    // If we have only one vorbis stream allow the stream id to change    // it's normal on radio stream (each song have an different id).    // But we (or the codec?) should check that the samplerate, etc    // doesn't change (for radio stream it's ok)    if(ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {      ogg_stream_reset(&ogg_d->subs[0].stream);      ogg_stream_init(&ogg_d->subs[0].stream,s_no);      id = 0;    } else      return -1;  }    if(os)    *os = &ogg_d->subs[id].stream;  return id;}static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,void *context,float* pts,int* flags, int samplesize) {  unsigned char* data;  *pts = 0;  *flags = 0;  if(os->vorbis) {    data = pack->packet;    if(*pack->packet & PACKET_TYPE_HEADER)      os->hdr_packets++;    else if (context )    {       vorbis_info *vi = &((ov_struct_t*)context)->vi;       // When we dump the audio, there is no vi, but we don't care of timestamp in this case       int32_t blocksize = vorbis_packet_blocksize(vi,pack) / samplesize;       // Calculate the timestamp if the packet don't have any       if(pack->granulepos == -1) {	  pack->granulepos = os->lastpos;	  if(os->lastsize > 0)	     pack->granulepos += os->lastsize;       }       *pts = pack->granulepos / (float)vi->rate;       os->lastsize = blocksize;       os->lastpos = pack->granulepos;    }# ifdef HAVE_OGGTHEORA  } else if (os->theora) {     /* we pass complete packets to theora, mustn't strip the header! */     data = pack->packet;     os->lastsize = 1;          /* header packets beginn on 1-bit: thus check (*data&0x80).  We don't	have theora_state st, until all header packets were passed to the	decoder. */     if (context != NULL && !(*data&0x80))     {        theora_info *thi = ((theora_struct_t*)context)->st.i;        int keyframe_granule_shift=_ilog(thi->keyframe_frequency_force-1);        int64_t iframemask = (1 << keyframe_granule_shift) - 1;	if (pack->granulepos >= 0)	{	   os->lastpos = pack->granulepos >> keyframe_granule_shift;	   os->lastpos += pack->granulepos & iframemask;	   *flags = ((pack->granulepos & iframemask) == 0);	}	else	{	   os->lastpos++;	}	pack->granulepos = os->lastpos;	*pts = (double)os->lastpos / (double)os->samplerate;

⌨️ 快捷键说明

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