1 /*
2  *  export_mp2enc.c
3  *
4  *  Georg Ludwig - January 2002
5  *
6  *  Parts of export_wav and export_mpeg2enc used for this file
7  *
8  *  This file is part of transcode, a video stream processing tool
9  *
10  *  transcode is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  transcode is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with GNU Make; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #define MOD_NAME    "export_mp2enc.so"
27 #define MOD_VERSION "v1.0.11 (2006-03-16)"
28 #define MOD_CODEC   "(audio) MPEG 1/2"
29 
30 #include "transcode.h"
31 #include "avilib/wavlib.h"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 
39 #define CLAMP(x,l,h) x > h ? h : x < l ? l : x
40 
41 static int 			verbose_flag	= TC_QUIET;
42 static int 			capability_flag	= TC_CAP_PCM;
43 
44 #define MOD_PRE mp2enc
45 #include "export_def.h"
46 
47 static FILE* 			pFile 		= NULL;
48 static WAV wav = NULL;
49 
50 /* ------------------------------------------------------------
51  *
52  * open outputfile
53  *
54  * ------------------------------------------------------------*/
55 
56 MOD_open
57 {
58     int verb;
59 
60     /* check for mp2enc */
61     if (tc_test_program("mp2enc") != 0) return (TC_EXPORT_ERROR);
62 
63     if (param->flag == TC_AUDIO)
64     {
65         char buf [PATH_MAX];
66 	char mono[] = "-m";
67 	char stereo[] = "-s";
68 	int srate, brate;
69 	char *chan;
70 	int def_srate, def_brate;
71 	char *def_chan;
72 
73         verb = (verbose & TC_DEBUG) ? 2:0;
74 
75 	srate = (vob->mp3frequency != 0) ? vob->mp3frequency : vob->a_rate;
76 	brate = vob->mp3bitrate;
77 	chan = (vob->dm_chan>=2) ? stereo : mono;
78 
79 	def_srate = srate;
80 	def_brate = brate;
81 	def_chan = chan;
82 
83 	// default profile values, authority: videohelp and dvdfaq
84 	switch(vob->mpeg_profile) {
85 	case VCD_PAL: case VCD_NTSC: case VCD:
86 	  def_srate = 44100;
87 	  def_brate = 224;
88 	  def_chan = stereo;
89 	  break;
90 	case SVCD_PAL: case SVCD_NTSC: case SVCD:
91 	  def_srate = 44100;
92 	  def_brate = CLAMP (brate, 64, 384);
93 	  def_chan = stereo;
94 	  break;
95 	case XVCD_PAL: case XVCD_NTSC: case XVCD:
96 	  // check for invalid sample rate
97 	  if ((srate != 32000) && (srate != 44100) && (srate != 48000))
98 	  	def_srate = 44100;
99 	  // don't change if valid rate
100 	  def_brate = CLAMP (brate, 64, 384);
101 	  def_chan = stereo;
102 	  break;
103 	case DVD_PAL: case DVD_NTSC: case DVD:
104 	  def_srate = 48000;
105 	  def_brate = CLAMP (brate, 64, 384);
106 	  def_chan = stereo;
107 	case PROF_NONE:
108 	  break;
109 	}
110 
111 	// encoding values, let commandline override profile
112 	if(!(vob->export_attributes & TC_EXPORT_ATTRIBUTE_ARATE))
113 	  if (srate != def_srate) {
114             tc_log_info(MOD_NAME, "export profile changed samplerate:"
115 			          " %d -> %d Hz.", srate, def_srate);
116 	    srate = def_srate;
117 	  }
118 	if(!(vob->export_attributes & TC_EXPORT_ATTRIBUTE_ABITRATE))
119 	  if (brate != def_brate) {
120             tc_log_info(MOD_NAME, "export profile changed bitrate: "
121 			          "%d -> %d kbps.", brate, def_brate);
122 	    brate = def_brate;
123 	  }
124 	if(!(vob->export_attributes & TC_EXPORT_ATTRIBUTE_ACHANS))
125 	  if (chan != def_chan) {
126             tc_log_info(MOD_NAME, "export profile changed channels: "
127 			          "mono -> stereo.");
128 	    chan = def_chan;
129 	  }
130 
131 	if(tc_snprintf(buf, PATH_MAX, "mp2enc -v %d -r %d -b %d %s -o \"%s\" %s", verb, srate, brate, chan, vob->audio_out_file, (vob->ex_a_string?vob->ex_a_string:"")) < 0) {
132 	  tc_log_perror(MOD_NAME, "cmd buffer overflow");
133 	  return(TC_EXPORT_ERROR);
134 	}
135 
136         if(verbose & TC_INFO) tc_log_info(MOD_NAME, "(%d/%d) cmd=%s",
137 			                  (int)strlen(buf), PATH_MAX, buf);
138 
139         if((pFile = popen (buf, "w")) == NULL)
140 	  return(TC_EXPORT_ERROR);
141 
142         wav = wav_fdopen(fileno(pFile), WAV_WRITE|WAV_PIPE, NULL);
143         if (wav == NULL) {
144       	    tc_log_perror(MOD_NAME, "open wave stream");
145       	    return TC_EXPORT_ERROR;
146         }
147 
148         wav_set_rate(wav, vob->a_rate);
149         wav_set_bitrate(wav, vob->dm_chan*vob->a_rate*vob->dm_bits/8);
150         wav_set_channels(wav, vob->dm_chan);
151         wav_set_bits(wav, vob->dm_bits);
152 
153         return(0);
154     }
155 
156     if (param->flag == TC_VIDEO)
157 	return(0);
158 
159     // invalid flag
160     return(TC_EXPORT_ERROR);
161 }
162 
163 
164 /* ------------------------------------------------------------
165  *
166  * init codec
167  *
168  * ------------------------------------------------------------*/
169 
170 MOD_init
171 {
172     if(param->flag == TC_AUDIO)
173     {
174         return(0);
175     }
176 
177     if (param->flag == TC_VIDEO)
178 	return(0);
179 
180     // invalid flag
181     return(TC_EXPORT_ERROR);
182 }
183 
184 /* ------------------------------------------------------------
185  *
186  * encode and export frame
187  *
188  * ------------------------------------------------------------*/
189 
190 
191 MOD_encode
192 {
193     if(param->flag == TC_AUDIO)
194     {
195 	if (wav_write_data(wav, param->buffer, param->size) != param->size)
196         {
197             tc_log_perror(MOD_NAME, "write audio frame");
198             return(TC_EXPORT_ERROR);
199         }
200         return (0);
201     }
202 
203     if (param->flag == TC_VIDEO)
204         return(0);
205 
206     // invalid flag
207     return(TC_EXPORT_ERROR);
208 }
209 
210 /* ------------------------------------------------------------
211  *
212  * stop encoder
213  *
214  * ------------------------------------------------------------*/
215 
216 MOD_stop
217 {
218     if (param->flag == TC_VIDEO)
219         return (0);
220 
221     if (param->flag == TC_AUDIO)
222 	return (0);
223 
224     return(TC_EXPORT_ERROR);
225 }
226 
227 /* ------------------------------------------------------------
228  *
229  * close codec
230  *
231  * ------------------------------------------------------------*/
232 
233 MOD_close
234 {
235     if (param->flag == TC_VIDEO)
236 	return (0);
237 
238     if (param->flag == TC_AUDIO)
239     {
240         if (wav != NULL) {
241             wav_close(wav);
242             wav = NULL;
243         }
244         if (pFile != NULL) {
245     	    pclose (pFile);
246             pFile = NULL;
247         }
248 
249         return(0);
250     }
251 
252     return (TC_EXPORT_ERROR);
253 }
254 
255