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

📄 demux_audio.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "config.h"#include "../mp_msg.h"#include <stdlib.h>#include <stdio.h>#include "stream.h"#include "demuxer.h"#include "stheader.h"#include "genres.h"#include "mp3_hdr.h"#include <string.h>#ifdef MP_DEBUG#include <assert.h>#endif#define MP3 1#define WAV 2#define fLaC 3#define HDR_SIZE 4typedef struct da_priv {  int frmt;  float last_pts;} da_priv_t;// how many valid frames in a row we need before accepting as valid MP3#define MIN_MP3_HDRS 5//! Used to describe a potential (chain of) MP3 headers we foundtypedef struct mp3_hdr {  off_t frame_pos; // start of first frame in this "chain" of headers  off_t next_frame_pos; // here we expect the next header with same parameters  int mp3_chans;  int mp3_freq;  int cons_hdrs; // if this reaches MIN_MP3_HDRS we accept as MP3 file  struct mp3_hdr *next;} mp3_hdr_t;extern void free_sh_audio(sh_audio_t* sh);extern void resync_audio_stream(sh_audio_t *sh_audio);extern void print_wave_header(WAVEFORMATEX *h);int hr_mp3_seek = 0;/** * \brief free a list of MP3 header descriptions * \param list pointer to the head-of-list pointer */static void free_mp3_hdrs(mp3_hdr_t **list) {  mp3_hdr_t *tmp;  while (*list) {    tmp = (*list)->next;    free(*list);    *list = tmp;  }}/** * \brief add another potential MP3 header to our list * If it fits into an existing chain this one is expanded otherwise * a new one is created. * All entries that expected a MP3 header before the current position * are discarded. * The list is expected to be and will be kept sorted by next_frame_pos * and when those are equal by frame_pos. * \param list pointer to the head-of-list pointer * \param st_pos stream position where the described header starts * \param mp3_chans number of channels as specified by the header * \param mp3_freq sampling frequency as specified by the header * \param mp3_flen length of the frame as specified by the header * \return If non-null the current file is accepted as MP3 and the * mp3_hdr struct describing the valid chain is returned. Must be * freed independent of the list. */static mp3_hdr_t *add_mp3_hdr(mp3_hdr_t **list, off_t st_pos,                               int mp3_chans, int mp3_freq, int mp3_flen) {  mp3_hdr_t *tmp;  int in_list = 0;  while (*list && (*list)->next_frame_pos <= st_pos) {    if (((*list)->next_frame_pos < st_pos) || ((*list)->mp3_chans != mp3_chans)         || ((*list)->mp3_freq != mp3_freq)) { // wasn't valid!      tmp = (*list)->next;      free(*list);      *list = tmp;    } else {      (*list)->cons_hdrs++;      (*list)->next_frame_pos = st_pos + mp3_flen;      if ((*list)->cons_hdrs >= MIN_MP3_HDRS) {        // copy the valid entry, so that the list can be easily freed        tmp = malloc(sizeof(mp3_hdr_t));        memcpy(tmp, *list, sizeof(mp3_hdr_t));        tmp->next = NULL;        return tmp;      }      in_list = 1;      list = &((*list)->next);    }  }  if (!in_list) { // does not belong into an existing chain, insert    tmp = malloc(sizeof(mp3_hdr_t));    tmp->frame_pos = st_pos;    tmp->next_frame_pos = st_pos + mp3_flen;    tmp->mp3_chans = mp3_chans;    tmp->mp3_freq = mp3_freq;    tmp->cons_hdrs = 1;    tmp->next = *list;    *list = tmp;  }  return NULL;}int demux_audio_open(demuxer_t* demuxer) {  stream_t *s;  sh_audio_t* sh_audio;  uint8_t hdr[HDR_SIZE];  int frmt = 0, n = 0, step, mp3_freq, mp3_chans, mp3_flen;  off_t st_pos = 0, next_frame_pos = 0;  // mp3_hdrs list is sorted first by next_frame_pos and then by frame_pos  mp3_hdr_t *mp3_hdrs = NULL, *mp3_found = NULL;  da_priv_t* priv;#ifdef MP_DEBUG  assert(demuxer != NULL);  assert(demuxer->stream != NULL);#endif    s = demuxer->stream;  stream_read(s, hdr, HDR_SIZE);  while(n < 30000 && !s->eof) {    st_pos = stream_tell(s) - HDR_SIZE;    step = 1;    if( hdr[0] == 'R' && hdr[1] == 'I' && hdr[2] == 'F' && hdr[3] == 'F' ) {      stream_skip(s,4);      if(s->eof)	break;      stream_read(s,hdr,4);      if(s->eof)	break;      if(hdr[0] != 'W' || hdr[1] != 'A' || hdr[2] != 'V'  || hdr[3] != 'E' )	stream_skip(s,-8);      else      // We found wav header. Now we can have 'fmt ' or a mp3 header      // empty the buffer	step = 4;    } else if( hdr[0] == 'I' && hdr[1] == 'D' && hdr[2] == '3' && (hdr[3] >= 2)) {      int len;      stream_skip(s,2);      stream_read(s,hdr,4);      len = (hdr[0]<<21) | (hdr[1]<<14) | (hdr[2]<<7) | hdr[3];      stream_skip(s,len);      step = 4;    } else if( hdr[0] == 'f' && hdr[1] == 'm' && hdr[2] == 't' && hdr[3] == ' ' ) {      frmt = WAV;      break;          } else if((mp3_flen = mp_get_mp3_header(hdr,&mp3_chans,&mp3_freq)) > 0) {      mp3_found = add_mp3_hdr(&mp3_hdrs, st_pos, mp3_chans, mp3_freq, mp3_flen);      if (mp3_found) {        frmt = MP3;        break;      }    } else if( hdr[0] == 'f' && hdr[1] == 'L' && hdr[2] == 'a' && hdr[3] == 'C' ) {      frmt = fLaC;      stream_skip(s,-4);      break;    }    // Add here some other audio format detection    if(step < HDR_SIZE)      memmove(hdr,&hdr[step],HDR_SIZE-step);    stream_read(s, &hdr[HDR_SIZE - step], step);    n++;  }  free_mp3_hdrs(&mp3_hdrs);  if(!frmt)    return 0;  sh_audio = new_sh_audio(demuxer,0);  switch(frmt) {  case MP3:    sh_audio->format = 0x55;    demuxer->movi_start = mp3_found->frame_pos;    next_frame_pos = mp3_found->next_frame_pos;    sh_audio->audio.dwSampleSize= 0;    sh_audio->audio.dwScale = 1152;    sh_audio->audio.dwRate = mp3_found->mp3_freq;    sh_audio->wf = malloc(sizeof(WAVEFORMATEX));    sh_audio->wf->wFormatTag = sh_audio->format;    sh_audio->wf->nChannels = mp3_found->mp3_chans;    sh_audio->wf->nSamplesPerSec = mp3_found->mp3_freq;    sh_audio->wf->nBlockAlign = 1152;    sh_audio->wf->wBitsPerSample = 16;    sh_audio->wf->cbSize = 0;        free(mp3_found);    mp3_found = NULL;    if(s->end_pos) {      char tag[4];      stream_seek(s,s->end_pos-128);      stream_read(s,tag,3);      tag[3] = '\0';      if(strcmp(tag,"TAG"))	demuxer->movi_end = s->end_pos;      else {	char buf[31];	uint8_t g;	demuxer->movi_end = stream_tell(s)-3;	stream_read(s,buf,30);	buf[30] = '\0';	demux_info_add(demuxer,"Title",buf);	stream_read(s,buf,30);	buf[30] = '\0';	demux_info_add(demuxer,"Artist",buf);	stream_read(s,buf,30);	buf[30] = '\0';	demux_info_add(demuxer,"Album",buf);	stream_read(s,buf,4);	buf[4] = '\0';	demux_info_add(demuxer,"Year",buf);	stream_read(s,buf,30);	buf[30] = '\0';	demux_info_add(demuxer,"Comment",buf);	if(buf[28] == 0 && buf[29] != 0) {	  uint8_t trk = (uint8_t)buf[29];	  sprintf(buf,"%d",trk);	  demux_info_add(demuxer,"Track",buf);	}	g = stream_read_char(s);	demux_info_add(demuxer,"Genre",genres[g]);      }    }    break;  case WAV: {    unsigned int chunk_type;    unsigned int chunk_size;    WAVEFORMATEX* w;    int l;    l = stream_read_dword_le(s);    if(l < 16) {      mp_msg(MSGT_DEMUX,MSGL_ERR,"[demux_audio] Bad wav header length: too short (%d)!!!\n",l);      free_sh_audio(sh_audio);      return 0;    }    sh_audio->wf = w = (WAVEFORMATEX*)malloc(l > sizeof(WAVEFORMATEX) ? l : sizeof(WAVEFORMATEX));    w->wFormatTag = sh_audio->format = stream_read_word_le(s);    w->nChannels = sh_audio->channels = stream_read_word_le(s);    w->nSamplesPerSec = sh_audio->samplerate = stream_read_dword_le(s);    w->nAvgBytesPerSec = stream_read_dword_le(s);    w->nBlockAlign = stream_read_word_le(s);    w->wBitsPerSample = sh_audio->samplesize = stream_read_word_le(s);    w->cbSize = 0;    l -= 16;    if (l > 0) {    w->cbSize = stream_read_word_le(s);    l -= 2;     if (w->cbSize > 0) {      if (l < w->cbSize) {        mp_msg(MSGT_DEMUX,MSGL_ERR,"[demux_audio] truncated extradata (%d < %d)\n",	l,w->cbSize);        stream_read(s,(char*)((char*)(w)+sizeof(WAVEFORMATEX)),l);        l = 0;      } else {        stream_read(s,(char*)((char*)(w)+sizeof(WAVEFORMATEX)),w->cbSize);

⌨️ 快捷键说明

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