1 /***************************************************************************
2 ADM_codecmp3.cpp - description
3 -------------------
4 begin : Fri May 31 2002
5 copyright : (C) 2002 by mean
6 email : fixounet@free.fr
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17 #include "ADM_default.h"
18 #include "ADM_ad_plugin.h"
19
20 #ifdef USE_EXTERNAL_LIBMAD
21 #include "mad.h"
22 #else
23 #include "ADM_libMad/mad.h"
24 #endif
25
26 #define Stream ((mad_stream *)_stream)
27 #define Frame ((mad_frame *)_frame)
28 #define Synth ((mad_synth *)_synth)
29
30 #define ADM_MP3_BUFFER (48*1024)
31 class ADM_AudiocodecMP3 : public ADM_Audiocodec
32 {
33 protected:
34 uint32_t _head;
35 uint32_t _tail;
36 uint8_t _buffer[ADM_MP3_BUFFER];
37 void *_stream;
38 void *_frame;
39 void *_synth;
40
41 public:
42 ADM_AudiocodecMP3(uint32_t fourcc,WAVHeader *info,uint32_t extraLength,uint8_t *extraData);
43 virtual ~ADM_AudiocodecMP3() ;
44 virtual bool resetAfterSeek(void);
45 virtual uint8_t run(uint8_t *inptr, uint32_t nbIn, float *outptr, uint32_t *nbOut);
isCompressed(void)46 virtual uint8_t isCompressed(void) {return 1;}
isDecompressable(void)47 virtual uint8_t isDecompressable(void) {return 1;}
48 };
49 // Supported formats + declare our plugin
50 //*******************************************************
51 static ad_supportedFormat Formats[]={
52 {WAV_MP3,AD_HIGH_QUAL},
53 {WAV_MP2,AD_HIGH_QUAL},
54
55 };
56
57
58 DECLARE_AUDIO_DECODER(ADM_AudiocodecMP3, // Class
59 0,0,1, // Major, minor,patch
60 Formats, // Supported formats
61 "LibMad decoder plugin for avidemux (c) Mean\n"); // Desc
62 //********************************************************
63
ADM_AudiocodecMP3(uint32_t fourcc,WAVHeader * info,uint32_t extraLength,uint8_t * extraData)64 ADM_AudiocodecMP3::ADM_AudiocodecMP3( uint32_t fourcc,WAVHeader *info,uint32_t extraLength,uint8_t *extraData)
65 : ADM_Audiocodec(fourcc,*info)
66 {
67 if((fourcc!=WAV_MP3) && (fourcc!=WAV_MP2))
68 ADM_assert(0);
69 if(fourcc==WAV_MP2) printf("Mpeg1/2 audio codec created\n");
70 _stream=(void *)ADM_alloc(sizeof( mad_stream));
71 _frame=(void *)ADM_alloc(sizeof( mad_frame));
72 _synth=(void *)ADM_alloc(sizeof( mad_synth));
73
74
75 mad_stream_init(Stream);
76 mad_frame_init(Frame);
77 mad_synth_init(Synth);
78
79 _head=_tail=0;
80
81 }
~ADM_AudiocodecMP3()82 ADM_AudiocodecMP3::~ADM_AudiocodecMP3( )
83 {
84 mad_synth_finish(Synth);
85 mad_frame_finish(Frame);
86 mad_stream_finish(Stream);
87 ADM_dealloc(_stream);
88 ADM_dealloc(_frame);
89 ADM_dealloc(_synth);
90 _synth=_synth=_stream=NULL;
91
92 }
resetAfterSeek(void)93 bool ADM_AudiocodecMP3::resetAfterSeek( void )
94 {
95 mad_synth_finish(Synth);
96 mad_frame_finish(Frame);
97 mad_stream_finish(Stream);
98
99 mad_stream_init(Stream);
100 mad_frame_init(Frame);
101 mad_synth_init(Synth);
102 _head=_tail=0;
103 return 1;
104 }
105
run(uint8_t * inptr,uint32_t nbIn,float * outptr,uint32_t * nbOut)106 uint8_t ADM_AudiocodecMP3::run(uint8_t * inptr, uint32_t nbIn, float *outptr, uint32_t * nbOut)
107 {
108 int i;
109 signed int Sample;
110 *nbOut = 0;
111 // Shrink ?
112 if(ADM_MP3_BUFFER<=_tail+nbIn)
113 {
114 memmove(_buffer,_buffer+_head,_tail-_head);
115 _tail-=_head;
116 _head=0;
117 }
118 ADM_assert(_tail+nbIn<ADM_MP3_BUFFER);
119 memcpy(_buffer+_tail,inptr,nbIn);
120 _tail+=nbIn;
121
122 // Now feed to libmad
123 mad_stream_buffer(Stream, _buffer+_head, _tail-_head);
124 while(1)
125 {
126 Stream->error = MAD_ERROR_NONE;
127 if ((i = mad_frame_decode(Frame, Stream)))
128 {
129 if (MAD_RECOVERABLE(Stream->error))
130 {
131 ADM_info("[Mad:Error] %x \n",(int)Stream->error);
132 } else
133 {
134 if (Stream->error == MAD_ERROR_BUFLEN) // we consumed everything
135 {
136 uint32_t left=0;
137 //printf("Empty,Stream.next_frame : %lx, Stream.bufend :%lx,delta :%ld",
138 // Stream.next_frame,Stream.bufend,Stream.bufend-Stream.next_frame);
139 // Update _head
140 if (Stream->next_frame != NULL)
141 {
142 left = Stream->bufend - Stream->next_frame;
143 }
144 ADM_assert(left<=_tail-_head);
145 _head=_tail-left;
146 return 1;
147 } else
148 {
149 fprintf(stderr," unrecoverable frame level error ");
150 return 0;
151 }
152 }
153 }
154
155 mad_synth_frame(Synth, Frame);
156 if (MAD_NCHANNELS(&(Frame->header)) == 2) {//Stereo
157 for (i = 0; i < Synth->pcm.length; i++) {
158 *(outptr++) = (float) mad_f_todouble(Synth->pcm.samples[0][i]);
159 *(outptr++) = (float) mad_f_todouble(Synth->pcm.samples[1][i]);
160 }
161 *nbOut += Synth->pcm.length * 2;
162 } else {//Mono
163 for (i = 0; i < Synth->pcm.length; i++) {
164 *(outptr++) = (float) mad_f_todouble(Synth->pcm.samples[0][i]);
165 }
166 *nbOut += Synth->pcm.length;
167 }
168 }
169
170 return 0;
171 }
172