1 /*
2  *  import_dv.c
3  *
4  *  Copyright (C) Thomas Oestreich - June 2001
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 #define MOD_NAME    "import_dv.so"
25 #define MOD_VERSION "v0.3.1 (2003-10-14)"
26 #define MOD_CODEC   "(video) DV | (audio) PCM"
27 
28 #include "transcode.h"
29 #include "libtc/libtc.h"
30 #include "libtc/xio.h"
31 #include "libtcvideo/tcvideo.h"
32 
33 static int verbose_flag = TC_QUIET;
34 static int capability_flag = TC_CAP_RGB | TC_CAP_YUV | TC_CAP_DV |
35     TC_CAP_PCM | TC_CAP_VID | TC_CAP_YUV422;
36 
37 #define MOD_PRE dv
38 #include "import_def.h"
39 
40 
41 char import_cmd_buf[TC_BUF_MAX];
42 
43 static int frame_size=0;
44 static FILE *fd=NULL;
45 static uint8_t *tmpbuf = NULL;
46 static int yuv422_mode = 0, width, height;
47 static TCVHandle tcvhandle = 0;
48 
49 /* ------------------------------------------------------------
50  *
51  * open stream
52  *
53  * ------------------------------------------------------------*/
54 
55 MOD_open
56 {
57 
58   char cat_buf[TC_BUF_MAX];
59   char yuv_buf[16];
60   long sret;
61 
62   if(param->flag == TC_VIDEO) {
63 
64     //directory mode?
65     sret = tc_file_check(vob->video_in_file);
66     if (sret < 0) {
67         return(TC_IMPORT_ERROR);
68     }
69     if(sret == 1) {
70         tc_snprintf(cat_buf, TC_BUF_MAX, "tccat");
71     } else {
72         if(vob->im_v_string) {
73             tc_snprintf(cat_buf, TC_BUF_MAX, "tcextract -x dv %s",
74 			            vob->im_v_string);
75         } else {
76             tc_snprintf(cat_buf, TC_BUF_MAX, "tcextract -x dv");
77         }
78     }
79 
80     //yuy2 mode?
81     (vob->dv_yuy2_mode) ?
82         tc_snprintf(yuv_buf, 16, "-y yuv420p -Y") :
83         tc_snprintf(yuv_buf, 16, "-y yuv420p");
84 
85     param->fd = NULL;
86     yuv422_mode = 0;
87 
88     switch(vob->im_v_codec) {
89 
90     case CODEC_RGB:
91 
92       sret = tc_snprintf(import_cmd_buf, TC_BUF_MAX,
93                       "%s -i \"%s\" -d %d | tcdecode -x dv -y rgb -d %d -Q %d",
94                       cat_buf, vob->video_in_file, vob->verbose, vob->verbose,
95                       vob->quality);
96       if (sret < 0)
97           return(TC_IMPORT_ERROR);
98 
99       // popen
100       if((param->fd = popen(import_cmd_buf, "r"))== NULL) {
101 	return(TC_IMPORT_ERROR);
102       }
103 
104       break;
105 
106     case CODEC_YUV:
107 
108       sret = tc_snprintf(import_cmd_buf, TC_BUF_MAX,
109 			 "%s -i \"%s\" -d %d | tcdecode -x dv %s -d %d -Q %d",
110 			 cat_buf, vob->video_in_file, vob->verbose, yuv_buf,
111 			 vob->verbose, vob->quality);
112       if (sret < 0)
113 	return(TC_IMPORT_ERROR);
114 
115       // for reading
116       frame_size = (vob->im_v_width * vob->im_v_height * 3)/2;
117 
118       param->fd = NULL;
119 
120       // popen
121       if((fd = popen(import_cmd_buf, "r"))== NULL) {
122 	return(TC_IMPORT_ERROR);
123       }
124 
125       break;
126 
127     case CODEC_YUV422:
128 
129       sret = tc_snprintf(import_cmd_buf, TC_BUF_MAX,
130 			 "%s -i \"%s\" -d %d |"
131 			 " tcdecode -x dv -y yuy2 -d %d -Q %d",
132 			 cat_buf, vob->video_in_file, vob->verbose,
133 			 vob->verbose, vob->quality);
134       if (sret < 0)
135 	return(TC_IMPORT_ERROR);
136 
137       // for reading
138       frame_size = vob->im_v_width * vob->im_v_height * 2;
139 
140       tmpbuf = tc_malloc(frame_size);
141       if (!tmpbuf) {
142 	tc_log_error(MOD_NAME, "out of memory");
143 	return(TC_IMPORT_ERROR);
144       }
145 
146       tcvhandle = tcv_init();
147       if (!tcvhandle) {
148 	tc_log_error(MOD_NAME, "tcv_init() failed");
149 	return(TC_IMPORT_ERROR);
150       }
151 
152       yuv422_mode = 1;
153       width = vob->im_v_width;
154       height = vob->im_v_height;
155 
156       param->fd = NULL;
157 
158       // popen
159       if((fd = popen(import_cmd_buf, "r"))== NULL) {
160 	return(TC_IMPORT_ERROR);
161       }
162 
163       break;
164 
165 
166     case CODEC_RAW:
167     case CODEC_RAW_YUV:
168 
169       sret = tc_snprintf(import_cmd_buf, TC_BUF_MAX, "%s -i \"%s\" -d %d",
170 			 cat_buf, vob->video_in_file, vob->verbose);
171       if (sret < 0)
172 	return(TC_IMPORT_ERROR);
173 
174       // for reading
175       frame_size = (vob->im_v_height==PAL_H) ?
176           TC_FRAME_DV_PAL : TC_FRAME_DV_NTSC;
177 
178       param->fd = NULL;
179 
180       // popen
181       if((fd = popen(import_cmd_buf, "r"))== NULL) {
182 	return(TC_IMPORT_ERROR);
183       }
184 
185       break;
186 
187 
188     default:
189       tc_log_warn(MOD_NAME, "invalid import codec request 0x%x",
190 		      vob->im_v_codec);
191       return(TC_IMPORT_ERROR);
192 
193     }
194 
195     // print out
196     if(verbose_flag) tc_log_info(MOD_NAME, "%s", import_cmd_buf);
197 
198     return(TC_IMPORT_OK);
199   }
200 
201   if(param->flag == TC_AUDIO) {
202 
203     //directory mode?
204     if(tc_file_check(vob->audio_in_file)) {
205         tc_snprintf(cat_buf, TC_BUF_MAX, "tccat");
206     } else {
207         if(vob->im_a_string) {
208             tc_snprintf(cat_buf, TC_BUF_MAX, "tcextract -x dv %s",
209             			vob->im_a_string);
210         } else {
211             tc_snprintf(cat_buf, TC_BUF_MAX, "tcextract -x dv");
212         }
213     }
214 
215     sret = tc_snprintf(import_cmd_buf, TC_BUF_MAX,
216 		       "%s -i \"%s\" -d %d | tcdecode -x dv -y pcm -d %d",
217 		       cat_buf, vob->audio_in_file, vob->verbose,
218 		       vob->verbose);
219     if (sret < 0)
220       return(TC_IMPORT_ERROR);
221 
222     // print out
223     if(verbose_flag) tc_log_info(MOD_NAME, "%s", import_cmd_buf);
224 
225     param->fd = NULL;
226 
227     // popen
228     if((param->fd = popen(import_cmd_buf, "r"))== NULL) {
229 	tc_log_perror(MOD_NAME, "popen PCM stream");
230 	return(TC_IMPORT_ERROR);
231     }
232 
233     return(TC_IMPORT_OK);
234   }
235 
236   return(TC_IMPORT_ERROR);
237 
238 }
239 
240 /* ------------------------------------------------------------
241  *
242  * decode  stream
243  *
244  * ------------------------------------------------------------*/
245 
246 MOD_decode
247 {
248 
249     if(param->flag == TC_AUDIO) return(TC_IMPORT_OK);
250 
251     // video and YUV only
252     if(param->flag == TC_VIDEO && frame_size==0) return(TC_IMPORT_ERROR);
253 
254     // return true yuv frame size as physical size of video data
255     param->size = frame_size;
256 
257     if (yuv422_mode) {
258         if (fread(tmpbuf, frame_size, 1, fd) !=1)
259             return(TC_IMPORT_ERROR);
260 	tcv_convert(tcvhandle, tmpbuf, param->buffer, width, height,
261 		    IMG_YUY2, IMG_YUV422P);
262     } else {
263         if (fread(param->buffer, frame_size, 1, fd) !=1)
264             return(TC_IMPORT_ERROR);
265     }
266 
267     return(TC_IMPORT_OK);
268 }
269 
270 /* ------------------------------------------------------------
271  *
272  * close stream
273  *
274  * ------------------------------------------------------------*/
275 
276 
277 MOD_close
278 {
279   if(param->fd != NULL) pclose(param->fd);
280 
281   if(param->flag == TC_AUDIO) return(TC_IMPORT_OK);
282 
283   if(param->flag == TC_VIDEO) {
284 
285     if(fd) pclose(fd);
286     fd=NULL;
287 
288     if (tcvhandle)
289       tcv_free(tcvhandle);
290     tcvhandle=0;
291 
292     free(tmpbuf);
293     tmpbuf=NULL;
294 
295     return(TC_IMPORT_OK);
296 
297   }
298 
299   return(TC_IMPORT_ERROR);
300 }
301 
302