1 /*
2  *  export_im.c
3  *
4  *  Copyright (C) Thomas Oestreich - March 2002
5  *
6  *  This file is part of transcode, a video stream processing tool
7  *
8  *  transcode is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2, or (at your option)
11  *  any later version.
12  *
13  *  transcode is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with GNU Make; see the file COPYING.  If not, write to
20  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23 
24 /* Note: because of ImageMagick bogosity, this must be included first, so
25  * we can undefine the PACKAGE_* symbols it splats into our namespace */
26 #include <magick/api.h>
27 #undef PACKAGE_BUGREPORT
28 #undef PACKAGE_NAME
29 #undef PACKAGE_STRING
30 #undef PACKAGE_TARNAME
31 #undef PACKAGE_VERSION
32 
33 #include "transcode.h"
34 #include "libtcvideo/tcvideo.h"
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 
39 #define MOD_NAME    "export_im.so"
40 #define MOD_VERSION "v0.0.4 (2003-11-13)"
41 #define MOD_CODEC   "(video) *"
42 
43 static int verbose_flag=TC_QUIET;
44 static int capability_flag=TC_CAP_YUV|TC_CAP_RGB|TC_CAP_PCM|TC_CAP_AUD;
45 
46 #define MOD_PRE im
47 #include "export_def.h"
48 
49 static char buf2[PATH_MAX];
50 
51 static uint8_t *tmp_buffer; //[SIZE_RGB_FRAME];
52 static TCVHandle tcvhandle;
53 
54 static int codec, width, height;
55 
56 static int counter=0;
57 static const char *prefix="frame.";
58 static const char *type;
59 
60 static int interval=1;
61 static unsigned int int_counter=0;
62 
63 ImageInfo *image_info;
64 
65 /* ------------------------------------------------------------
66  *
67  * init codec
68  *
69  * ------------------------------------------------------------*/
70 
71 MOD_init
72 {
73 
74     /* set the 'spit-out-frame' interval */
75     interval = vob->frame_interval;
76 
77     if(param->flag == TC_VIDEO) {
78       int quality = 75;
79 
80       width = vob->ex_v_width;
81       height = vob->ex_v_height;
82 
83       codec = (vob->im_v_codec == CODEC_YUV) ? CODEC_YUV : CODEC_RGB;
84 
85       InitializeMagick("");
86 
87       image_info=CloneImageInfo((ImageInfo *) NULL);
88 
89       if (vob->divxbitrate == VBITRATE)
90 	quality = 75;
91       else quality = vob->divxbitrate;
92 
93       if (quality >= 100) quality = 100;
94       if (quality <= 0) quality = 0;
95 
96       image_info->quality = quality;
97 
98       if (!tmp_buffer)
99 	tmp_buffer = malloc (vob->ex_v_width*vob->ex_v_height*3);
100       if (!tmp_buffer)
101 	return TC_EXPORT_ERROR;
102 
103       tcvhandle = tcv_init();
104       if (!tcvhandle) {
105 	tc_log_error(MOD_NAME, "tcv_init() failed");
106 	return TC_EXPORT_ERROR;
107       }
108 
109       return TC_EXPORT_OK;
110     }
111 
112     if(param->flag == TC_AUDIO)
113       return TC_EXPORT_OK;
114 
115     // invalid flag
116     return TC_EXPORT_ERROR;
117 }
118 
119 /* ------------------------------------------------------------
120  *
121  * open outputfile
122  *
123  * ------------------------------------------------------------*/
124 
125 MOD_open
126 {
127 
128     if(param->flag == TC_VIDEO) {
129 
130       // video
131 
132 	switch(vob->im_v_codec) {
133 
134 	case CODEC_YUV:
135 	case CODEC_RGB:
136 
137 	  if(vob->video_out_file!=NULL && strcmp(vob->video_out_file,"/dev/null")!=0) prefix=vob->video_out_file;
138 
139 	  break;
140 
141 	default:
142 
143 	  tc_log_warn(MOD_NAME, "codec not supported");
144 	  return(TC_EXPORT_ERROR);
145 
146 	  break;
147 	}
148 
149 	if(vob->ex_v_fcc != NULL && strlen(vob->ex_v_fcc) != 0) {
150 	  type = vob->ex_v_fcc;
151 	} else type="jpg";
152 
153 	return(0);
154     }
155 
156 
157     if(param->flag == TC_AUDIO) return(0);
158 
159     // invalid flag
160     return(TC_EXPORT_ERROR);
161 }
162 
163 /* ------------------------------------------------------------
164  *
165  * encode and export
166  *
167  * ------------------------------------------------------------*/
168 
169 MOD_encode
170 {
171 
172   ExceptionInfo exception_info;
173   char *out_buffer = param->buffer;
174   Image *image=NULL;
175   int res;
176 
177   if ((++int_counter-1) % interval != 0)
178       return (0);
179 
180   if(param->flag == TC_VIDEO) {
181 
182     GetExceptionInfo(&exception_info);
183 
184     res = tc_snprintf(buf2, PATH_MAX, "%s%06d.%s", prefix, counter++, type);
185     if (res < 0) {
186       tc_log_perror(MOD_NAME, "cmd buffer overflow");
187       return(TC_EXPORT_ERROR);
188     }
189 
190     if(codec==CODEC_YUV) {
191       tcv_convert(tcvhandle, param->buffer, tmp_buffer, width, height,
192 		  IMG_YUV_DEFAULT, IMG_RGB24);
193       out_buffer = tmp_buffer;
194     }
195 
196     image=ConstituteImage (width, height, "RGB", CharPixel, out_buffer, &exception_info);
197 
198     strlcpy(image->filename, buf2, MaxTextExtent);
199 
200     WriteImage(image_info, image);
201     DestroyImage(image);
202 
203     return(0);
204   }
205 
206   if(param->flag == TC_AUDIO) return(0);
207 
208   // invalid flag
209   return(TC_EXPORT_ERROR);
210 }
211 
212 /* ------------------------------------------------------------
213  *
214  * stop encoder
215  *
216  * ------------------------------------------------------------*/
217 
218 MOD_stop
219 {
220 
221   if(param->flag == TC_VIDEO) {
222     DestroyImageInfo(image_info);
223     ConstituteComponentTerminus();
224     DestroyMagick();
225 
226     free(tmp_buffer);
227     tmp_buffer = NULL;
228     tcv_free(tcvhandle);
229     tcvhandle = 0;
230 
231     return(0);
232   }
233 
234   if(param->flag == TC_AUDIO) return(0);
235 
236   return(TC_EXPORT_ERROR);
237 }
238 
239 /* ------------------------------------------------------------
240  *
241  * close outputfiles
242  *
243  * ------------------------------------------------------------*/
244 
245 MOD_close
246 {
247 
248     if(param->flag == TC_AUDIO) return(0);
249     if(param->flag == TC_VIDEO) return(0);
250 
251     return(TC_EXPORT_ERROR);
252 
253 }
254 
255