summaryrefslogtreecommitdiffstats
path: root/libmpcodecs/dec_audio.c
blob: 835e5b870f7d2d0c04d3535c48b961c4809ae981 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "config.h"
#include "mp_msg.h"
#include "help_mp.h"

extern int verbose; // defined in mplayer.c

#include "stream.h"
#include "demuxer.h"

#include "codec-cfg.h"
#include "stheader.h"

#include "dec_audio.h"
#include "ad.h"
#include "../libao2/afmt.h"

#ifdef USE_FAKE_MONO
int fakemono=0;
#endif
/* used for ac3surround decoder - set using -channels option */
int audio_output_channels = 2;

static ad_functions_t* mpadec;

int init_audio(sh_audio_t *sh_audio)
{
  unsigned i;
  for (i=0; mpcodecs_ad_drivers[i] != NULL; i++)
    if(mpcodecs_ad_drivers[i]->info->id==sh_audio->codec->driver){
	mpadec=mpcodecs_ad_drivers[i]; break;
    }
  if(!mpadec){
      mp_msg(MSGT_DECAUDIO,MSGL_ERR,"Requested audio codec family [%s] (vfm=%d) not available (enable it at compile time!)\n",
          sh_audio->codec->name, sh_audio->codec->driver);
      return 0; // no such driver
  }
  
  printf("Selecting Audio Decoder: [%s] %s\n",mpadec->info->short_name,mpadec->info->name);
  
  sh_audio->samplesize=2;
#ifdef WORDS_BIGENDIAN
  sh_audio->sample_format=AFMT_S16_BE;
#else
  sh_audio->sample_format=AFMT_S16_LE;
#endif
  sh_audio->samplerate=0;
  sh_audio->o_bps=0;

  sh_audio->a_buffer_size=0;
  sh_audio->a_buffer=NULL;

  sh_audio->a_in_buffer_len=0;

  /* setup required min. in/out buffer size:*/
  sh_audio->audio_out_minsize=8192;/* default size, maybe not enough for Win32/ACM*/
  
  if(!mpadec->preinit(sh_audio))
  {
      printf("ADecoder preinit failed :(\n");
      return 0;
  }

/* allocate audio out buffer: */
  sh_audio->a_buffer_size=sh_audio->audio_out_minsize+MAX_OUTBURST; /* worst case calc.*/

  mp_msg(MSGT_DECAUDIO,MSGL_V,"dec_audio: Allocating %d + %d = %d bytes for output buffer\n",
      sh_audio->audio_out_minsize,MAX_OUTBURST,sh_audio->a_buffer_size);

  sh_audio->a_buffer=malloc(sh_audio->a_buffer_size);
  if(!sh_audio->a_buffer){
      mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_CantAllocAudioBuf);
      return 0;
  }
  memset(sh_audio->a_buffer,0,sh_audio->a_buffer_size);
  sh_audio->a_buffer_len=0;

  if(!mpadec->init(sh_audio)){
      printf("ADecoder init failed :(\n");
      return 0;
  }
  sh_audio->inited=1;
  
  if(!sh_audio->channels || !sh_audio->samplerate){
    mp_msg(MSGT_DECAUDIO,MSGL_WARN,MSGTR_UnknownAudio);
    if(sh_audio->a_buffer) free(sh_audio->a_buffer);
    sh_audio->a_buffer=NULL;
    return 0;
  }

  if(!sh_audio->o_bps)
  sh_audio->o_bps=sh_audio->channels*sh_audio->samplerate*sh_audio->samplesize;
  return sh_audio->codec->driver;
}

void uninit_audio(sh_audio_t *sh_audio)
{
    if(!sh_audio->inited) return;
    mp_msg(MSGT_DECAUDIO,MSGL_V,"uninit audio: %d  \n",sh_audio->codec->driver);
    mpadec->uninit(sh_audio);
    if(sh_audio->a_buffer) free(sh_audio->a_buffer);
    sh_audio->a_buffer=NULL;
    sh_audio->inited=0;
}

int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen)
{
  if(sh_audio->inited) 
    return mpadec->decode_audio(sh_audio,buf,minlen,maxlen);
  else
    return -1;
}

void resync_audio_stream(sh_audio_t *sh_audio)
{
  if(!sh_audio->inited) return;
  if(mpadec->control(sh_audio,ADCTRL_RESYNC_STREAM,NULL)==CONTROL_TRUE) return;
  // default resync code:
  sh_audio->a_in_buffer_len=0;        // clear audio input buffer
}

void skip_audio_frame(sh_audio_t *sh_audio)
{
  if(!sh_audio->inited) return;
  if(mpadec->control(sh_audio,ADCTRL_SKIP_FRAME,NULL)==CONTROL_TRUE) return;
  // default skip code:
  ds_fill_buffer(sh_audio->ds);  // skip block
}