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

📄 conversion.c

📁 基于linux的DVD播放器程序
💻 C
字号:
/* Ogle - A video player * Copyright (C) 2002 Bj鰎n Englund, H錵an Hjort * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdio.h>#include <unistd.h> // swab#include <string.h> // memset#include <mad.h>#include "debug_print.h"#include "conversion.h"#include "decode_private.h" // Fixme#include "ogle_endian.h"/* * needs to know input and output format * * channel configuration * sample rate * nr_samples * sample precision * sample encoding */typedef struct {  int *channel_conf;} conversion_t;static ChannelType_t ch_transform[10];static int dst_ch;static int conversion_routine = 0;void setup_channel_conf(int *ch_conf, int nr_ch, int *input_ch, int *output_ch){  int n,m;  for(n = 0; n < nr_ch; n++) {    for(m = 0; m < nr_ch; m++) {      if(input_ch[m] == output_ch[n]) {	ch_conf[n] = m;	break;      }    }  }  }int init_sample_conversion(adec_handle_t *h,			   audio_format_t *src_format,			   int nr_samples){  // nr samples, the max number of samples that will be converted  // between each play  int m;  int n;  audio_format_t *dst_format = &h->config->dst_format;  int output_frame_size = h->config->dst_format.sample_frame_size;    h->config->src_format = *src_format;  if(src_format->sample_format == SampleFormat_DTSFrame) {        if(h->output_buf_size < nr_samples * output_frame_size) {      h->output_buf_size = nr_samples * output_frame_size;      h->output_buf = realloc(h->output_buf, h->output_buf_size);      if(h->output_buf == NULL) {	FATAL("%s", "init_sample_conversion2, realloc failed\n");	exit(1); // ?      }    }      } else if(src_format->sample_format == SampleFormat_AC3Frame) {        if(h->output_buf_size < 256*6*2*2) {      h->output_buf_size = 256*6*2*2;      h->output_buf = realloc(h->output_buf, h->output_buf_size);      if(h->output_buf == NULL) {	FATAL("%s", "init_sample_conversion2, realloc failed\n");	exit(1); // ?      }    }      } else {    if(h->output_buf_size < nr_samples * output_frame_size) {      h->output_buf_size = nr_samples * output_frame_size;      h->output_buf = realloc(h->output_buf, h->output_buf_size);      if(h->output_buf == NULL) {	FATAL("%s", "init_sample_conversion, realloc failed\n");	exit(1); // ?      }    }    //fprintf(stderr, "output_buf: %ld\n", (long)h->output_buf);    //fprintf(stderr, "output_buf_size: %d\n", h->output_buf_size);    h->output_buf_ptr = h->output_buf;        dst_ch = dst_format->nr_channels;    if(dst_ch > 10) {      FATAL("%s", "*** more than 10 channels\n");      exit(1);    }    for(n = 0; n < dst_format->nr_channels; n++) {      for(m = 0; m < src_format->nr_channels; m++) {	if(dst_format->ch_array[n] == src_format->ch_array[m]) {	  ch_transform[n] = m;	  break;	}      }      if(m == src_format->nr_channels) {	//type not in src	ch_transform[n] = -1;      }    }  }  // setup the conversion functions  // from the sample buffer format to the output buffer format  switch(src_format->sample_format) {  case SampleFormat_A52float:    conversion_routine = 0;    break;  case SampleFormat_Signed:    conversion_routine = 1;    break;  case SampleFormat_MadFixed:    conversion_routine = 2;    break;  case SampleFormat_AC3Frame:    conversion_routine = 3;    break;  case SampleFormat_DTSFrame:    conversion_routine = 4;    break;  case SampleFormat_LPCM:    conversion_routine = 5;    break;  case SampleFormat_Unsigned:  default:    FATAL("init_conversion: SampleFormat %d not supported\n",	  src_format->sample_format);    break;  }  return 0;}static inline int16_t convert (int32_t i){    if (i > 0x43c07fff)	return 32767;    else if (i < 0x43bf8000)	return -32768;    else	return i - 0x43c00000;}static int convert_a52_float_to_s16(float * _f, int16_t *s16, int nr_samples,				int nr_channels, int *channels){  int i;  int n;  int32_t *f = (int32_t *)_f;    // assert(nr_channels == 2);      // assert(nr_samples == 256);  for (i = 0; i < nr_samples; i++) {    for(n = 0; n < dst_ch; n++) {      if(ch_transform[n] != -1) {	s16[dst_ch*i+n] = convert(f[i+ch_transform[n]*256]);      } else {	s16[dst_ch*i+n] = 0;      }    }  }      return 0;}/** code borrowed from vlc **/static inline int16_t convert_mad(mad_fixed_t fixed){  /* round */  fixed += (1L << (MAD_F_FRACBITS - 16));    /* clip */  if (fixed >= MAD_F_ONE)    fixed = MAD_F_ONE - 1;  else if (fixed < -MAD_F_ONE)    fixed = -MAD_F_ONE;    /* quantize */  return (int16_t)(fixed >> (MAD_F_FRACBITS + 1 - 16));}static int convert_mad_fixed_to_s16(mad_fixed_t *m, int16_t *s16,				    int nr_samples,				    int nr_channels, int *channels){  int i;    // assert(nr_channels == 2);        for (i = 0; i < nr_samples; i++) {    s16[2*i] = convert_mad(m[i]);    s16[2*i+1] = convert_mad(m[i+1152]);  }    return 0;}static int convert_s16be_to_s16ne(int16_t *s16be, int16_t *s16ne,				  int nr_samples, int nr_channels,				  int *channels){#if WORDS_BIGENDIAN == 1  memcpy(s16ne, s16be, nr_samples * nr_channels * sizeof(int16_t));#else  int i;  for (i = 0; i < nr_samples * nr_channels; i++) {    ((uint16_t *)s16ne)[i] =      ((((uint16_t *)s16be)[i] >> 8) & 0xff) |       ((((uint16_t *)s16be)[i] << 8) & 0xff00);  }#endif    return 0;}struct frmsize_s{  uint16_t bit_rate;  uint16_t frm_size[3];};static const struct frmsize_s frmsizecod_tbl[64] ={  { 32  ,{64   ,69   ,96   } },  { 32  ,{64   ,70   ,96   } },  { 40  ,{80   ,87   ,120  } },  { 40  ,{80   ,88   ,120  } },  { 48  ,{96   ,104  ,144  } },  { 48  ,{96   ,105  ,144  } },  { 56  ,{112  ,121  ,168  } },  { 56  ,{112  ,122  ,168  } },  { 64  ,{128  ,139  ,192  } },  { 64  ,{128  ,140  ,192  } },  { 80  ,{160  ,174  ,240  } },  { 80  ,{160  ,175  ,240  } },  { 96  ,{192  ,208  ,288  } },  { 96  ,{192  ,209  ,288  } },  { 112 ,{224  ,243  ,336  } },  { 112 ,{224  ,244  ,336  } },  { 128 ,{256  ,278  ,384  } },  { 128 ,{256  ,279  ,384  } },  { 160 ,{320  ,348  ,480  } },  { 160 ,{320  ,349  ,480  } },  { 192 ,{384  ,417  ,576  } },  { 192 ,{384  ,418  ,576  } },  { 224 ,{448  ,487  ,672  } },  { 224 ,{448  ,488  ,672  } },  { 256 ,{512  ,557  ,768  } },  { 256 ,{512  ,558  ,768  } },  { 320 ,{640  ,696  ,960  } },  { 320 ,{640  ,697  ,960  } },  { 384 ,{768  ,835  ,1152 } },  { 384 ,{768  ,836  ,1152 } },  { 448 ,{896  ,975  ,1344 } },  { 448 ,{896  ,976  ,1344 } },  { 512 ,{1024 ,1114 ,1536 } },  { 512 ,{1024 ,1115 ,1536 } },  { 576 ,{1152 ,1253 ,1728 } },  { 576 ,{1152 ,1254 ,1728 } },  { 640 ,{1280 ,1393 ,1920 } },  { 640 ,{1280 ,1394 ,1920 } }};static int convert_ac3frame_to_iec61937frame(uint16_t *ac3,					     uint16_t *iec61937,					     int nr_samples){    uint32_t fscod,frmsizecod,bsmod,frame_size;  uint8_t *data_out = (uint8_t *)iec61937;  uint8_t *data_in = (uint8_t *)ac3;  int frame_bytes;    if (ac3[0] != 0x770b) {    fprintf(stderr, "SYNC/////////\n");  }  fscod = (data_in[4] >> 6) & 0x3;  frmsizecod = data_in[4] & 0x3f;  bsmod = data_in[5] & 0x7;		// bsmod, stream = 0  frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] ;    data_out[0] = 0x72; data_out[1] = 0xf8;	/* iec61937 Preamble Pa */  data_out[2] = 0x1f; data_out[3] = 0x4e;	/*                   Pb */  data_out[4] = 0x01;			        /* AC3               Pc */  data_out[5] = bsmod;			        /* bsmod, stream = 0    */  data_out[6] = (frame_size << 4) & 0xff;       /* frame_size * 16   Pd */  data_out[7] = ((frame_size ) >> 4) & 0xff;  swab(data_in, &data_out[8], frame_size * 2 );  //  fprintf(stderr, "frame_size: %d\n", frame_size);  frame_bytes = frame_size * 2 + 8;  memset(&data_out[frame_bytes], 0, 256*6*2*2 - frame_bytes);  return 0;}static int convert_dtsframe_to_iec61937frame(uint16_t *dts,					     uint16_t *iec61937,					     int nr_samples){    uint8_t *data_out = (uint8_t *)iec61937;  uint8_t *data_in = (uint8_t *)dts;  int fsize;  int burst_len;    fsize = (data_in[5] & 0x03) << 12 |    (data_in[6] << 4) | (data_in[7] >> 4);  fsize = fsize + 1;  burst_len = fsize * 8;  data_out[0] = 0x72; data_out[1] = 0xf8;	/* iec 61937     */  data_out[2] = 0x1f; data_out[3] = 0x4e;	/*  syncword     */  switch(nr_samples) {  case 512:    data_out[4] = 0x0b;			/* DTS-1 (512-sample bursts) */    break;  case 1024:    data_out[4] = 0x0c;			/* DTS-2 (1024-sample bursts) */    break;  case 2048:    data_out[4] = 0x0d;			/* DTS-3 (2048-sample bursts) */    break;  default:    FATAL("IEC61937-5: %d-sample bursts not supported\n", nr_samples);    data_out[4] = 0x00;    break;  }  data_out[5] = 0;                      /* ?? */	     data_out[6] = (burst_len) & 0xff;     data_out[7] = (burst_len >> 8) & 0xff;    if(fsize+8 > nr_samples*2*2) {    ERROR("%s", "IEC61937-5: more data than fits\n");  }  //TODO if fzise is odd, swab doesn't copy the last byte  swab(data_in, &data_out[8], fsize);  //  fprintf(stderr, "frame_size: %d\n", frame_size);  memset(&data_out[fsize+8], 0, nr_samples*2*2 - (fsize+8));  return 0;}static int convert_LPCM_to_sXXne(uint8_t *lpcm, void *output,				 int nr_samples,				 audio_format_t *src_format,				 audio_format_t *dst_format){  int i,n,ct;  int src_ch = src_format->nr_channels;  int unaligned = ((uint32_t)lpcm) % 2;  if(src_format->nr_channels != 2) {    FATAL("REPORT BUG: convert from %d lpcm channels not implemented\n",	  src_format->nr_channels);    exit(1);  } else if (dst_format->nr_channels != 2) {    FATAL("REPORT BUG: convert to %d lpcm channels not implemented\n",	  dst_format->nr_channels);    exit(1);  }      switch(src_format->sample_resolution) {  case 16:    switch(dst_format->sample_resolution) {    case 16:      for (i = 0; i < nr_samples; i++) {	for(n = 0; n < dst_ch; n++) {	  if((ct = ch_transform[n]) != -1) {	    if(unaligned) {	      ((int16_t *)output)[dst_ch*i+n] =		(lpcm[2*(i*src_ch+ct)] << 8) | lpcm[2*(i*src_ch+ct)+1];	    } else {	      ((int16_t *)output)[dst_ch*i+n] = 		FROM_BE_16(((int16_t *)lpcm)[i*src_ch+ct]);	    }	  } else {	    ((int16_t *)output)[dst_ch*i+n] = 0;	  }	}      }      break;    case 32:      for (i = 0; i < nr_samples; i++) {	for(n = 0; n < dst_ch; n++) {	  if((ct = ch_transform[n]) != -1) {	    if(unaligned) {	      ((int32_t *)output)[dst_ch*i+n] =		(lpcm[2*(i*src_ch+ct)] <<24) | (lpcm[2*(i*src_ch+ct)+1] <<16);	    } else {	      ((int32_t *)output)[dst_ch*i+n] = 		FROM_BE_16(((int16_t *)lpcm)[i*src_ch+ct])<<16;	    }	  } else {	    ((int32_t *)output)[dst_ch*i+n] = 0;	  }	}      }      break;    default:      FATAL("REPORT BUG: convert from 16 to %d bits lpcm not implemented\n",	    dst_format->sample_resolution);      break;    }    break;  case 24:    switch(dst_format->sample_resolution) {      int s;    case 16:      for (i = 0, s = 0; i < nr_samples; s+=1) {	int j;	for(j = 0; j < 2; j++, i++,s++) {	  for(n = 0; n < dst_ch; n++) {	    if((ct = ch_transform[n]) != -1) {	      if(unaligned) {		((int16_t *)output)[dst_ch*i+n] =		  (lpcm[2*(s*src_ch+ct)] << 8) | lpcm[2*(s*src_ch+ct)+1];	      } else {		((int16_t *)output)[dst_ch*i+n] = 		  FROM_BE_16(((int16_t *)lpcm)[s*src_ch+ct]);	      }	    } else {	      ((int16_t *)output)[dst_ch*i+n] = 0;	    }	  }	}      }      break;    case 32:      for (i = 0, s = 0; i < nr_samples; s+=1) {	int j;	uint8_t *lsb = (uint8_t *)&((int16_t *)lpcm)[(s+2)*src_ch];	for(j = 0; j < 2; j++, i++, s++, lsb+=src_ch) {	  for(n = 0; n < dst_ch; n++) {	    if((ct = ch_transform[n]) != -1) {	      if(unaligned) {		((int32_t *)output)[dst_ch*i+n] =		  (lpcm[2*(s*src_ch+ct)] << 24) | 		  (lpcm[2*(s*src_ch+ct)+1] << 16) |		  lsb[ct] << 8;	      } else {		((int32_t *)output)[dst_ch*i+n] = 		  FROM_BE_16(((int16_t *)lpcm)[s*src_ch+ct]) << 16 |		  lsb[ct] << 8;	      }	    } else {	      ((int32_t *)output)[dst_ch*i+n] = 0;	    }	  }	}      }      break;    default:      FATAL("REPORT BUG: convert from 24 to %d bits lpcm not implemented\n",	    dst_format->sample_resolution);      break;    }    break;  default:    FATAL("REPORT BUG: convert %d bits lpcm not implemented\n",	  src_format->sample_resolution);    break;  }  return nr_samples*dst_format->sample_frame_size;}int convert_samples(adec_handle_t *h, void *samples, int nr_samples){  //convert from samples to output_buf_ptr  /*  fprintf(stderr, "samples: %d, output_buf_ptr: %d\n",	  samples, h->output_buf_ptr);  */  audio_format_t *src_format = &h->config->src_format;  audio_format_t *dst_format = &h->config->dst_format;  switch(conversion_routine) {  case 0:    convert_a52_float_to_s16((float *)samples, (int16_t *)h->output_buf_ptr, 			     nr_samples, 2, NULL);    h->output_buf_ptr += 2*dst_ch*nr_samples; // 2byte per sample    break;  case 1:    convert_s16be_to_s16ne(samples, (int16_t *)h->output_buf_ptr,			   nr_samples, 2, NULL);    h->output_buf_ptr += 2*2*nr_samples;    break;  case 2:    convert_mad_fixed_to_s16((mad_fixed_t *)samples,			     (int16_t *)h->output_buf_ptr, 			     nr_samples, 2, NULL);    h->output_buf_ptr += 2*2*nr_samples; // 2ch 2byte    break;  case 3:    convert_ac3frame_to_iec61937frame(samples,				      (uint16_t *)h->output_buf_ptr, 				      nr_samples);    h->output_buf_ptr += 256*6*2*2; // 2ch 16bit 48kHz (256*6 samples)        break;  case 4:    convert_dtsframe_to_iec61937frame(samples,				      (uint16_t *)h->output_buf_ptr, 				      nr_samples);    h->output_buf_ptr += 2*2*nr_samples; // 2ch 16bit 48kHz        break;  case 5:    h->output_buf_ptr += convert_LPCM_to_sXXne(samples, h->output_buf_ptr,					       nr_samples,					       src_format, dst_format);    break;  }   return 0;}void convert_samples_start(adec_handle_t *h){  h->output_buf_ptr = h->output_buf;}

⌨️ 快捷键说明

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