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