1 /* 2 * export_dvraw.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 "export_dvraw.so" 25 #define MOD_VERSION "v0.4.1 (2007-08-17)" 26 #define MOD_CODEC "(video) Digital Video | (audio) PCM" 27 28 #include "transcode.h" 29 #include "libtc/libtc.h" 30 #include "libtc/optstr.h" 31 #include "libtcvideo/tcvideo.h" 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <libdv/dv.h> 36 37 static int verbose_flag=TC_QUIET; 38 static int capability_flag=TC_CAP_PCM|TC_CAP_RGB|TC_CAP_YUV|TC_CAP_VID|TC_CAP_YUV422; 39 40 #define MOD_PRE dvraw 41 #include "export_def.h" 42 43 static int fd = -1; 44 45 /* only 2 channesl supported */ 46 #define MAX_CHANNELS 2 47 static int16_t *audio_bufs[MAX_CHANNELS] = { NULL, NULL }; 48 49 static uint8_t *target = NULL, *vbuf = NULL; 50 51 static dv_encoder_t *encoder = NULL; 52 static uint8_t *pixels[3] = { NULL, NULL, NULL }, *tmp_buf = NULL; 53 static TCVHandle tcvhandle; 54 55 static int frame_size = 0, format = 0; 56 static int pass_through = 0; 57 58 static int chans = 0, rate = 0; 59 static int dv_yuy2_mode = 0; 60 static int dv_uyvy_mode = 0; 61 static int is_PAL = 0; 62 63 /* ------------------------------------------------------------ 64 * 65 * init codec 66 * 67 * ------------------------------------------------------------*/ 68 69 MOD_init 70 { 71 int i; 72 73 if (param->flag == TC_VIDEO) { 74 is_PAL = (vob->ex_v_height == PAL_H); 75 target = tc_bufalloc(TC_FRAME_DV_PAL); 76 vbuf = tc_bufalloc(PAL_W * PAL_H * 3); 77 78 tcvhandle = tcv_init(); 79 80 if (vob->dv_yuy2_mode == 1) { 81 tmp_buf = tc_bufalloc(PAL_W * PAL_H * 2); //max frame 82 dv_yuy2_mode = 1; 83 } 84 85 if (vob->im_v_codec == CODEC_YUV422) { 86 tmp_buf = tc_bufalloc(PAL_W * PAL_H * 2); //max frame 87 dv_uyvy_mode = 1; 88 } 89 90 encoder = dv_encoder_new(FALSE, FALSE, FALSE); 91 return TC_OK; 92 } 93 94 if (param->flag == TC_AUDIO) { 95 // tmp audio buffer 96 for ( i = 0; i < MAX_CHANNELS; i++) { 97 audio_bufs[i] = tc_malloc(DV_AUDIO_MAX_SAMPLES * sizeof(int16_t)); 98 if (!(audio_bufs[i])) { 99 tc_log_error(MOD_NAME, "out of memory"); 100 return TC_ERROR; 101 } 102 } 103 return TC_OK; 104 } 105 106 return(TC_ERROR); 107 } 108 109 /* ------------------------------------------------------------ 110 * 111 * open outputfile 112 * 113 * ------------------------------------------------------------*/ 114 115 MOD_open 116 { 117 int bytealignment = 0, bytespersecond = 0, bytesperframe = 0; 118 119 if (param->flag == TC_VIDEO) { 120 fd = open(vob->video_out_file, O_RDWR|O_CREAT|O_TRUNC, 121 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 122 if (fd < 0) { 123 tc_log_perror(MOD_NAME, "open file"); 124 return TC_ERROR; 125 } 126 127 switch (vob->im_v_codec) { 128 case CODEC_RGB: 129 format = 0; 130 if (verbose >= TC_DEBUG) 131 tc_log_info(MOD_NAME, "raw format is RGB"); 132 break; 133 case CODEC_YUV: 134 format = 1; 135 if (verbose >= TC_DEBUG) 136 tc_log_info(MOD_NAME, "raw format is YUV420P"); 137 break; 138 case CODEC_YUV422: 139 format = 2; 140 if (verbose >= TC_DEBUG) 141 tc_log_info(MOD_NAME, "raw format is YUV422"); 142 break; 143 case CODEC_RAW: 144 case CODEC_RAW_YUV: 145 format = 1; 146 pass_through = 1; 147 break; 148 default: 149 tc_log_warn(MOD_NAME, "codec not supported"); 150 return TC_ERROR; 151 } 152 153 frame_size = (is_PAL) ?TC_FRAME_DV_PAL :TC_FRAME_DV_NTSC; 154 155 if (verbose >= TC_DEBUG) 156 tc_log_info(MOD_NAME, "encoding to %s DV", 157 (is_PAL) ?"PAL" :"NTSC"); 158 159 // Store aspect ratio - ex_asr uses the value 3 for 16x9 (XXX: tricky) 160 encoder->is16x9 = (((vob->ex_asr < 0) ?vob->im_asr :vob->ex_asr) == 3); 161 encoder->isPAL = is_PAL; 162 encoder->vlc_encode_passes = 3; 163 encoder->static_qno = 0; 164 if (vob->ex_v_string != NULL) 165 if (optstr_get(vob->ex_v_string, "qno", "%d", &encoder->static_qno) == 1) 166 tc_log_info(MOD_NAME, "using quantisation: %d", encoder->static_qno); 167 encoder->force_dct = DV_DCT_AUTO; 168 169 return TC_OK; 170 } 171 172 if (param->flag == TC_AUDIO) { 173 if (!encoder) { 174 tc_log_warn(MOD_NAME, "-y XXX,dvraw is not possible without the video"); 175 tc_log_warn(MOD_NAME, "export module also being dvraw"); 176 return TC_ERROR; 177 } 178 chans = vob->dm_chan; 179 //re-sampling only with -J resample possible 180 rate = vob->a_rate; 181 182 bytealignment = (chans == 2) ?4 :2; 183 bytespersecond = rate * bytealignment; 184 bytesperframe = bytespersecond/(is_PAL ?25 :30); 185 186 if(verbose >= TC_DEBUG) 187 tc_log_info(MOD_NAME, "audio: CH=%d, f=%d, balign=%d, bps=%d, bpf=%d", 188 chans, rate, bytealignment, bytespersecond, bytesperframe); 189 190 return TC_OK; 191 } 192 return TC_ERROR; 193 } 194 195 /* ------------------------------------------------------------ 196 * 197 * encode and export 198 * 199 * ------------------------------------------------------------*/ 200 201 MOD_encode 202 { 203 int i; 204 205 if (param->flag == TC_VIDEO) { 206 if (pass_through) { 207 ac_memcpy(target, param->buffer, frame_size); 208 } else { 209 ac_memcpy(vbuf, param->buffer, param->size); 210 } 211 212 return TC_OK; 213 } 214 215 if (param->flag == TC_AUDIO) { 216 int16_t *abufs[2] = { audio_bufs[0], audio_bufs[1] }; /* working copies */ 217 time_t now = time(NULL); 218 int achans = chans; 219 220 if (!pass_through) { 221 if (dv_uyvy_mode) { 222 tcv_convert(tcvhandle, 223 vbuf, tmp_buf, PAL_W, (encoder->isPAL) ? PAL_H : NTSC_H, 224 (format==2) ? IMG_YUV422P : IMG_YUV420P, IMG_UYVY); 225 pixels[0] = pixels[1] = pixels[2] = tmp_buf; 226 } else if (dv_yuy2_mode) { 227 tcv_convert(tcvhandle, 228 vbuf, tmp_buf, PAL_W, (encoder->isPAL) ? PAL_H : NTSC_H, 229 (format==2) ? IMG_YUV422P : IMG_YUV420P, IMG_YUY2); 230 pixels[0] = pixels[1] = pixels[2] = tmp_buf; 231 } else { 232 pixels[0] = vbuf; 233 if (encoder->isPAL) { 234 pixels[1] = pixels[0] + PAL_W*PAL_H; 235 pixels[2] = pixels[1] + (PAL_W/2)*(format==2?PAL_H:PAL_H/2); 236 } else { 237 pixels[1] = pixels[0] + NTSC_W*NTSC_H; 238 pixels[2] = pixels[1] + (NTSC_W/2)*(format==2?NTSC_H:NTSC_H/2); 239 } 240 } 241 242 dv_encode_full_frame(encoder, pixels, (format)?e_dv_color_yuv:e_dv_color_rgb, target); 243 } //no pass-through 244 /* 245 * samples * channels * bits = size; 246 * so 247 * samples = size / (channels * bits) 248 */ 249 encoder->samples_this_frame = param->size / (chans * sizeof(int16_t)); 250 dv_encode_metadata(target, encoder->isPAL, encoder->is16x9, &now, 0); 251 dv_encode_timecode(target, encoder->isPAL, 0); 252 253 #ifdef WORDS_BIGENDIAN 254 for (i=0; i<param->size; i+=2) { 255 uint8_t tmp = param->buffer[i]; 256 param->buffer[i] = param->buffer[i+1]; 257 param->buffer[i+1] = tmp; 258 } 259 #endif 260 261 // Although dv_encode_full_audio supports 4 channels, the internal 262 // PCM data (param->buffer) is only carrying 2 channels so only deal 263 // with 1 or 2 channel audio. 264 // Work around apparent bug in dv_encode_full_audio when chans == 1 265 // by putting silence in 2nd channel and calling with chans = 2 266 if (chans == 1) { 267 abufs[0] = (int16_t *)param->buffer; /* avoid ac_memcpy */ 268 memset(abufs[1], 0, DV_AUDIO_MAX_SAMPLES * 2); 269 achans = 2; 270 } else { 271 // assume 2 channel, demultiplex for libdv API 272 for(i = 0; i < param->size/4; i++) { // XXX magic number 273 abufs[0][i] = ((int16_t *)param->buffer)[i * 2 ]; 274 abufs[1][i] = ((int16_t *)param->buffer)[i * 2 + 1]; 275 } 276 } 277 dv_encode_full_audio(encoder, abufs, achans, rate, target); 278 279 if (tc_pwrite(fd, target, frame_size) != frame_size) { 280 tc_log_perror(MOD_NAME, "write frame"); 281 return TC_ERROR; 282 } 283 284 return TC_OK; 285 } 286 287 return TC_ERROR; 288 } 289 290 /* ------------------------------------------------------------ 291 * 292 * stop encoder 293 * 294 * ------------------------------------------------------------*/ 295 296 MOD_stop 297 { 298 int i; 299 300 if (param->flag == TC_VIDEO) { 301 dv_encoder_free(encoder); 302 tcv_free(tcvhandle); 303 return TC_OK; 304 } 305 306 if (param->flag == TC_AUDIO) { 307 for(i = 0; i < MAX_CHANNELS; i++) 308 tc_free(audio_bufs[i]); 309 return TC_OK; 310 } 311 312 return TC_ERROR; 313 } 314 315 /* ------------------------------------------------------------ 316 * 317 * close outputfiles 318 * 319 * ------------------------------------------------------------*/ 320 321 MOD_close 322 { 323 if(param->flag == TC_VIDEO) { 324 close(fd); 325 return TC_OK; 326 } 327 328 if (param->flag == TC_AUDIO) 329 return TC_OK; 330 331 return TC_ERROR; 332 } 333 334 335