Fix crash with partial fribidi conversion.
[mplayer/greg.git] / libmpcodecs / ad_hwmpa.c
blobca60fcf69fc9747c9ccb3c92eb58dc45e6013a9b
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
6 #include "config.h"
8 #include "mp_msg.h"
9 #include "help_mp.h"
11 #include "libaf/af_format.h"
12 #include "ad_internal.h"
14 #include "libmpdemux/mp3_hdr.h"
16 //based on ad_hwac3.c and ad_libmad.c
18 static ad_info_t info =
20 "MPEG audio pass-through (fake decoder)",
21 "hwmpa",
22 "NicoDVB",
23 "NicoDVB",
24 "For hardware decoders"
27 LIBAD_EXTERN(hwmpa)
29 static int mpa_sync(sh_audio_t *sh, int no_frames, int *n, int *chans, int *srate, int *spf, int *mpa_layer, int *br)
31 int cnt = 0, x = 0, len, frames_count;
33 frames_count = 0;
36 while(cnt + 4 < sh->a_in_buffer_len)
38 x = mp_get_mp3_header(&(sh->a_in_buffer[cnt]), chans, srate, spf, mpa_layer, br);
39 if(x > 0)
41 frames_count++;
42 if(frames_count == no_frames)
44 *n = x;
45 return cnt;
48 cnt++;
50 len = demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len],sh->a_in_buffer_size-sh->a_in_buffer_len);
51 if(len > 0)
52 sh->a_in_buffer_len += len;
53 } while(len > 0);
54 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Cannot sync MPA frame: %d\r\n", len);
55 return -1;
58 static int preinit(sh_audio_t *sh)
60 sh->audio_out_minsize = 4608;//check
61 sh->audio_in_minsize = 4608;//check
62 sh->sample_format = AF_FORMAT_MPEG2;
63 return 1;
66 static int init(sh_audio_t *sh)
68 int cnt, chans, srate, spf, mpa_layer, br, len;
70 if((cnt = mpa_sync(sh, 1, &len, &chans, &srate, &spf, &mpa_layer, &br)) < 0)
71 return 0;
73 sh->channels = chans;
74 sh->samplerate = srate;
75 sh->i_bps = br * 125;
76 sh->samplesize = 2;
78 mp_msg(MSGT_DECAUDIO,MSGL_V,"AC_HWMPA initialized, bitrate: %d kb/s\r\n", len);
79 return 1;
82 static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen)
84 int len, start, tot;
85 int chans, srate, spf, mpa_layer, br;
86 int tot2;
88 tot = tot2 = 0;
90 while(tot2 < maxlen)
92 start = mpa_sync(sh, 1, &len, &chans, &srate, &spf, &mpa_layer, &br);
93 if(start < 0 || tot2 + spf * 2 * chans > maxlen)
94 break;
96 if(start + len > sh->a_in_buffer_len)
98 int l;
99 l = FFMIN(sh->a_in_buffer_size - sh->a_in_buffer_len, start + len);
100 l = demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len], l);
101 if(! l)
102 break;
103 sh->a_in_buffer_len += l;
104 continue;
107 memcpy(&buf[tot], &(sh->a_in_buffer[start]), len);
108 tot += len;
110 sh->a_in_buffer_len -= start + len;
111 memmove(sh->a_in_buffer, &(sh->a_in_buffer[start + len]), sh->a_in_buffer_len);
112 tot2 += spf * 2 * chans;
114 /* HACK: seems to fix most A/V sync issues */
115 break;
118 memset(&buf[tot], 0, tot2-tot);
119 return tot2;
123 static int control(sh_audio_t *sh,int cmd,void* arg, ...)
125 int start, len;
127 switch(cmd)
129 case ADCTRL_RESYNC_STREAM:
130 if(mpa_sync(sh, 1, &len, NULL, NULL, NULL, NULL, NULL) >= 0)
131 return CONTROL_TRUE;
132 else
133 return CONTROL_FALSE;
134 case ADCTRL_SKIP_FRAME:
135 start = mpa_sync(sh, 2, &len, NULL, NULL, NULL, NULL, NULL);
136 if(len < 0)
137 return CONTROL_FALSE;
139 sh->a_in_buffer_len -= start;
140 memmove(sh->a_in_buffer, &(sh->a_in_buffer[start]), sh->a_in_buffer_len);
141 return CONTROL_TRUE;
143 return CONTROL_UNKNOWN;
147 static void uninit(sh_audio_t *sh)