diff options
| author | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-09-11 14:38:47 +0900 |
|---|---|---|
| committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-09-11 14:38:47 +0900 |
| commit | 884c8093d63402a1ad0b502244b791e3c6782be3 (patch) | |
| tree | a600d4ab0d431a2bdfe4c15b70df43c14fbd8dd0 /debian/transcode/transcode-1.1.7/export/export_divx5.c | |
| parent | 14e1aa2006796f147f3f4811fb908a6b01e79253 (diff) | |
| download | extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.tar.gz extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.zip | |
Added debian extra dependency packages.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'debian/transcode/transcode-1.1.7/export/export_divx5.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/export/export_divx5.c | 778 |
1 files changed, 778 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/export/export_divx5.c b/debian/transcode/transcode-1.1.7/export/export_divx5.c new file mode 100644 index 00000000..c4f7aa02 --- /dev/null +++ b/debian/transcode/transcode-1.1.7/export/export_divx5.c @@ -0,0 +1,778 @@ +/* + * export_divx5.c + * + * Copyright (C) Thomas Oestreich - June 2001 + * + * 2-pass code OpenDivX port: "-R 1", "-R 2" + * Copyright (C) 2001 Christoph Lampert <gruel@web.de> + * + * constant quantizer extensions "-R 3" by Gerhard Monzel + * <gerhard.monzel@sap.com> + * + * This module is derived from export_divx4.c, minor modification by + * Christoph Lampert <gruel@web.de> + * + * This file is part of transcode, a video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <math.h> +#include <stdint.h> + +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#else +# ifdef OS_DARWIN +# include "libdldarwin/dlfcn.h" +# endif +#endif + + + +#ifdef HAVE_ENCORE2_H +#include <encore2.h> +#else +#include "divx5_encore2.h" +#endif +#include "transcode.h" +#include "avilib/avilib.h" +#include "aud_aux.h" +#include "vbr.h" + +#define MOD_NAME "export_divx5.so" +#define MOD_VERSION "v0.1.8 (2003-07-24)" +#define MOD_CODEC "(video) DivX 5.xx | (audio) MPEG/AC3/PCM" + +static int verbose_flag=TC_QUIET; +static int capability_flag=TC_CAP_PCM|TC_CAP_RGB|TC_CAP_YUV|TC_CAP_AC3|TC_CAP_AUD; + +#define MOD_PRE divx5 +#include "export_def.h" + +int VbrMode=0; +int force_key_frame=-1; + +static avi_t *avifile=NULL; + +//temporary audio/video buffer +static char *buffer; + +#if ENCORE_VERSION >= 20021024 +DivXBitmapInfoHeader *format =NULL; +void* encore_handle = NULL; +SETTINGS *settings = NULL; +char *logfile_mv=NULL; +#else +ENC_PARAM *divx; +#endif +ENC_FRAME encode; +ENC_RESULT key; + +// dl stuff +static int (*divx5_encore)(void *para0, int opt, void *para1, void *para2); +static void *handle; +static char module[TC_BUF_MAX]; + +#if ENCORE_VERSION >= 20021024 +static char * prof2name(int n) +{ + switch (n) { + case 0: return "Free/No profile"; + case 1: return "Handheld"; + case 2: return "Portable"; + case 3: return "Home Theatre"; + case 4: return "High Definition"; + default: return "Free/No profile"; + } +} +#endif + + +#define MODULE "libdivxencore.so.0" + +static int divx5_init(const char *path) { + const char *error; + int *quiet_encore; + + tc_snprintf(module, sizeof(module), "%s/%s", path, MODULE); + + + // try transcode's module directory + + handle = dlopen(module, RTLD_NOW); + + if (!handle) { + + //try the default: + + handle = dlopen(MODULE, RTLD_GLOBAL| RTLD_LAZY); + + if (!handle) { + tc_log_warn(MOD_NAME, "%s", dlerror()); + return(-1); + } else { + if(verbose_flag & TC_DEBUG) + tc_log_info(MOD_NAME, "Loading external codec module %s", MODULE); + } + + } else { + if(verbose_flag & TC_DEBUG) + tc_log_info(MOD_NAME, "Loading external codec module %s", module); + } + + divx5_encore = dlsym(handle, "encore"); + + if ((error = dlerror()) != NULL) { + tc_log_warn(MOD_NAME, "%s", error); + return(-1); + } + + quiet_encore=dlsym(handle, "quiet_encore"); + + if ((error = dlerror()) != NULL) { + tc_log_warn(MOD_NAME, "%s", error); + return(-1); + } + + *quiet_encore=1; + + // debug + if(verbose_flag & TC_STATS) *quiet_encore=0; + + return(0); +} + + +/* ------------------------------------------------------------ + * + * init codec + * + * ------------------------------------------------------------*/ + +MOD_init +{ + +#if ENCORE_VERSION >= 20021024 +#else + struct stat fbuf; +#endif + int ch; + + tc_log_warn(MOD_NAME, "*** Warning: DivX is broken and support for it is ***"); + tc_log_warn(MOD_NAME, "*** obsolete in transcode. Sooner or later it ***"); + tc_log_warn(MOD_NAME, "*** will be removed from transcode. Don't use ***"); + tc_log_warn(MOD_NAME, "*** DivX. Use xvid or ffmpeg -F mpeg4 instead ***"); + tc_log_warn(MOD_NAME, "*** for all your mpeg4 encodings. ***"); + + if(param->flag == TC_VIDEO) { + + //check for odd frame parameter: + + if((ch = vob->ex_v_width - ((vob->ex_v_width>>3)<<3)) != 0) { + tc_log_warn(MOD_NAME, "frame width %d (no multiple of 8)", vob->ex_v_width); + tc_log_warn(MOD_NAME, "encoder may not work correctly or crash"); + + if(ch & 1) { + tc_log_warn(MOD_NAME, "invalid frame width"); + return(TC_EXPORT_ERROR); + } + } + + if((ch = vob->ex_v_height - ((vob->ex_v_height>>3)<<3)) != 0) { + tc_log_warn(MOD_NAME, "frame height %d (no multiple of 8)", vob->ex_v_height); + tc_log_warn(MOD_NAME, "encoder may not work correctly or crash"); + + if(ch & 1) { + tc_log_warn(MOD_NAME, "invalid frame height"); + return(TC_EXPORT_ERROR); + } + } + + if ((buffer = malloc(vob->ex_v_height*vob->ex_v_width*3))==NULL) { + tc_log_perror(MOD_NAME, "out of memory"); + return(TC_EXPORT_ERROR); + } else + + memset(buffer, 0, vob->ex_v_height*vob->ex_v_width*3); + + //load the codec + + if(divx5_init(vob->mod_path)<0) { + tc_log_warn(MOD_NAME, "failed to init DivX 5.0 Codec"); + return(TC_EXPORT_ERROR); + } + + if (divx5_encore(0, ENC_OPT_VERSION, 0, 0) != ENCORE_VERSION) { + tc_log_warn(MOD_NAME, "API in encore.h is not compatible with installed lbdivxencore library"); + return (TC_EXPORT_ERROR); + } + + VbrMode = vob->divxmultipass; + // 0 for nothing, + // 1 for DivX 5.0 - first-pass, + // 2 for DivX 5.0 - second pass + // 3 constant quantizer + +#if ENCORE_VERSION >= 20021024 +#define FOURCC(A, B, C, D) ( ((uint8_t) (A)) | (((uint8_t) (B))<<8) | (((uint8_t) (C))<<16) | (((uint8_t) (D))<<24) ) + + if ((settings = malloc(sizeof(SETTINGS)))==NULL) { + tc_log_perror(MOD_NAME, "out of memory"); + return(TC_EXPORT_ERROR); + } + if ((format = malloc(sizeof(DivXBitmapInfoHeader)))==NULL) { + tc_log_perror(MOD_NAME, "out of memory"); + return(TC_EXPORT_ERROR); + } + memset (settings, 0, sizeof(SETTINGS)); + memset (format, 0, sizeof(DivXBitmapInfoHeader)); + + format->biSize = sizeof(DivXBitmapInfoHeader); + format->biWidth = vob->ex_v_width; + format->biHeight = vob->ex_v_height; + format->biCompression = (vob->im_v_codec==CODEC_RGB)?0:FOURCC('Y','V','1','2'); + format->biBitCount = (vob->im_v_codec==CODEC_RGB)?24:0; + + switch (vob->ex_frc) { + case 1: // 23.976 + settings->input_clock = 24000; + settings->input_frame_period = 1001; + break; + case 2: // 24.000 + settings->input_clock = 24000; + settings->input_frame_period = 1000; + break; + case 3: // 25.000 + settings->input_clock = 25000; + settings->input_frame_period = 1000; + break; + case 4: // 29.970 + settings->input_clock = 30000; + settings->input_frame_period = 1001; + break; + case 5: // 30.000 + settings->input_clock = 30000; + settings->input_frame_period = 1000; + break; + case 0: // notset + default: + settings->input_clock = (int)vob->ex_fps*1000; + settings->input_frame_period = 1000; + break; + } + + if (vob->divxlogfile && *vob->divxlogfile) { + if ((logfile_mv = malloc (strlen(vob->divxlogfile)+4)) == NULL) { + tc_log_error(MOD_NAME, "Cannot allocate memory for logfile_mv"); + return(TC_EXPORT_ERROR); + } + tc_snprintf(logfile_mv, strlen(vob->divxlogfile)+4, "%s_mv", vob->divxlogfile); + } + + // default -- expose this to user? + settings->complexity_modulation = 0.5; + + settings->bitrate = vob->divxbitrate*1000; + settings->max_key_interval = vob->divxkeyframes; + + settings->quality = vob->divxquality; + + if (VbrMode == 1 || VbrMode == 2){ + /* + * http://www.divx.com/support/divx/guide_mac.php + * + * Handheld 128000,262144,196608 + * Portable 768000,1048576,786432 + * Home Theatre Theatre 4000000,3145728,2359296 + * High Definition 8000000,6291456,4718592 + */ + + switch (vob->divx5_vbv_prof) { + case 1: // Handheld + settings->vbv_bitrate = 128000; + settings->vbv_size = 262144; + settings->vbv_occupancy = 196608; + break; + case 2: // Portable + settings->vbv_bitrate = 768000; + settings->vbv_size = 1048576; + settings->vbv_occupancy = 786432; + break; + case 3: // Home Theatre + settings->vbv_bitrate = 4000000; + settings->vbv_size = 3145728; + settings->vbv_occupancy = 2359296; + break; + case 4: // High Definition + settings->vbv_bitrate = 8000000; + settings->vbv_size = 6291456; + settings->vbv_occupancy = 4718592; + break; + case 0: // Free/user supplied + default: + settings->vbv_bitrate = vob->divx5_vbv_bitrate*400; + settings->vbv_size = vob->divx5_vbv_size*16384; + settings->vbv_occupancy = vob->divx5_vbv_occupancy*64; + break; + } + if (verbose & TC_DEBUG) + tc_log_info(MOD_NAME, "Using VBV Profile [%d] (%s)", + vob->divx5_vbv_prof, + prof2name(vob->divx5_vbv_prof)); + + } + + switch(VbrMode) { + case 0: + break; + settings->vbr_mode = RCMODE_VBV_1PASS; + case 1: + settings->vbr_mode = RCMODE_VBV_MULTIPASS_1ST; + settings->mv_file = logfile_mv; + settings->log_file_read = NULL; + settings->log_file_write = vob->divxlogfile; + + break; + case 2: + settings->vbr_mode = RCMODE_VBV_MULTIPASS_NTH; + settings->mv_file = logfile_mv; + settings->log_file_read = vob->divxlogfile; + // segfaults if !NULL; + settings->log_file_write = NULL; + + break; + + case 3: + settings->vbr_mode = RCMODE_1PASS_CONSTANT_Q; + settings->quantizer = vob->divxbitrate; + break; + } + + // bframes .. lets see how to handle it + // the codec is crippled anyway + settings->use_bidirect = 0; + + // don't need this. + settings->enable_crop = 0; + settings->enable_resize = 0; + + if(divx5_encore(&encore_handle, ENC_OPT_INIT, format, settings) < 0) { + tc_log_warn(MOD_NAME, "Error doing ENC_OPT_INIT"); + return(TC_EXPORT_ERROR); + } + +#else + + if ((divx = malloc(sizeof(ENC_PARAM)))==NULL) { + tc_log_perror(MOD_NAME, "out of memory"); + return(TC_EXPORT_ERROR); + } + + memset(divx, 0, sizeof(ENC_PARAM)); + + //important parameter (Note: use_bidirect and obmc have been removed since DivX4) + + divx->x_dim = vob->ex_v_width; + divx->y_dim = vob->ex_v_height; + divx->framerate = vob->ex_fps; + divx->bitrate = vob->divxbitrate*1000; + + //recommended (advanced) parameter + + divx->min_quantizer = vob->min_quantizer; + divx->max_quantizer = vob->max_quantizer; + divx->rc_period = vob->rc_period; + divx->rc_reaction_period = vob->rc_reaction_period; + divx->rc_reaction_ratio = vob->rc_reaction_ratio; + + divx->max_key_interval = vob->divxkeyframes; + divx->quality = vob->divxquality; + + divx->deinterlace=(vob->deinterlace==2) ? 1:0; // fast deinterlace = 1 + divx->handle=NULL; + + if(divx5_encore(NULL, ENC_OPT_INIT, divx, NULL) < 0) { + tc_log_warn(MOD_NAME, "DivX codec init error"); + return(TC_EXPORT_ERROR); + } + + // catch API mismatch + if(!divx || !divx->handle) { + tc_log_warn(MOD_NAME, "DivX codec open error"); + return(TC_EXPORT_ERROR); + } + + if(verbose_flag & TC_DEBUG) + { + //-- GMO start -- + if (vob->divxmultipass == 3) { + tc_log_info(MOD_NAME, " single-pass session: %d (VBR)", vob->divxmultipass); + tc_log_info(MOD_NAME, " VBR-quantizer: %d", vob->divxbitrate); + } else { + tc_log_info(MOD_NAME, " multi-pass session: %d", vob->divxmultipass); + tc_log_info(MOD_NAME, " bitrate [kBits/s]: %d", divx->bitrate/1000); + } + + tc_log_info(MOD_NAME, " quality: %d", divx->quality); + //-- GMO end -- + + tc_log_info(MOD_NAME, " crispness: %d", vob->divxcrispness); + tc_log_info(MOD_NAME, " max keyframe interval: %d", divx->max_key_interval); + tc_log_info(MOD_NAME, " frame rate: %.2f", vob->ex_fps); + tc_log_info(MOD_NAME, " color space: %s", (vob->im_v_codec==CODEC_RGB) ? "RGB24" : "YUV420P"); + tc_log_info(MOD_NAME, " deinterlace: %d", divx->deinterlace); + } + + encode.colorspace = (vob->im_v_codec==CODEC_RGB) ? ENC_CSP_RGB24:ENC_CSP_I420; + encode.mvs = NULL; + + encode.bitstream = buffer; + + + switch(VbrMode) { + + case 1: + VbrControl_init_2pass_vbr_analysis(vob->divxlogfile, divx->quality); + break; + + case 2: + + // check for logfile + + if(vob->divxlogfile==NULL || stat(vob->divxlogfile, &fbuf)){ + tc_log_warn(MOD_NAME, "pass-1 logfile \"%s\" not found exit", + vob->divxlogfile); + return(TC_EXPORT_ERROR); + } + + + // second pass: read back the logfile + VbrControl_init_2pass_vbr_encoding(vob->divxlogfile, + divx->bitrate, + divx->framerate, + vob->divxcrispness, + divx->quality); + break; + + //-- GMO start -- + case 3: + VbrControl_init_2pass_vbr_analysis(vob->divxlogfile, divx->quality); + + encode.quant = vob->divxbitrate; + encode.intra = -1; + break; + //-- GMO end -- + + default: + // none + break; + } +#endif + + return(TC_EXPORT_OK); + } + + if(param->flag == TC_AUDIO) { + tc_log_warn(MOD_NAME, "Usage of this module for audio encoding is deprecated."); + tc_log_warn(MOD_NAME, "Consider switch to export_tcaud module."); + return(tc_audio_init(vob, verbose)); + } + + // invalid flag + return(TC_EXPORT_ERROR); +} + + +/* ------------------------------------------------------------ + * + * open outputfile + * + * ------------------------------------------------------------*/ + +MOD_open +{ + + // open file + if(vob->avifile_out==NULL) + if(NULL == (vob->avifile_out = AVI_open_output_file(vob->video_out_file))) { + AVI_print_error("avi open error"); + return(TC_EXPORT_ERROR); + } + + /* save locally */ + avifile = vob->avifile_out; + + if(param->flag == TC_AUDIO) return(tc_audio_open(vob, vob->avifile_out)); + + if(param->flag == TC_VIDEO) { + + // video +#if ENCORE_MAJOR_VERSION >= 5010 + AVI_set_video(vob->avifile_out, vob->ex_v_width, vob->ex_v_height, + vob->ex_fps, "DX50"); +#else + AVI_set_video(vob->avifile_out, vob->ex_v_width, vob->ex_v_height, + vob->ex_fps, "DIVX"); +#endif + + if (vob->avi_comment_fd>0) + AVI_set_comment_fd(vob->avifile_out, vob->avi_comment_fd); + + //do not force key frame at the very beginning of encoding, since + //first frame will be a key fame anayway. Therefore key.quantizer + //is well defined for any frame to follow + force_key_frame=(force_key_frame<0) ? 0:1; + + return(0); + } + + // invalid flag + return(TC_EXPORT_ERROR); +} + + +/* ------------------------------------------------------------ + * + * encode and export frame + * + * ------------------------------------------------------------*/ + + +MOD_encode +{ + + if(param->flag == TC_VIDEO) { + + // encode video + + encode.image = param->buffer; + encode.bitstream = buffer; + +#if ENCORE_VERSION >= 20021024 + encode.produce_empty_frame = 0; + + do { + if(divx5_encore(encore_handle, ENC_OPT_ENCODE, &encode, &key) < 0) { + tc_log_warn(MOD_NAME, "DivX encoder error"); + return(TC_EXPORT_ERROR); + } + // write bitstream + if(key.cType != '\0') { + /* split the AVI */ + if((uint32_t)(AVI_bytes_written(avifile)+encode.length+16+8)>>20 >= tc_avi_limit) + tc_outstream_rotate_request(); + + //0.6.2: switch outfile on "C" and -J pv + if(key.cType == 'I') tc_outstream_rotate(); + + if(AVI_write_frame(avifile, buffer, encode.length, (key.cType == 'I')?1:0)<0) { + tc_log_warn(MOD_NAME, "DivX avi video write error"); + return(TC_EXPORT_ERROR); + } + } + encode.image = NULL; + } while (encode.length >= 0 && key.cType != '\0'); +#else + switch(VbrMode) { + + //-- GMO start -- + case 3: + + if (force_key_frame) + { + encode.intra = 1; + force_key_frame = 0; + } + else + encode.intra = -1; + + if(divx5_encore(divx->handle, ENC_OPT_ENCODE_VBR, &encode, &key) < 0) + { + tc_log_warn(MOD_NAME, "encoder error"); + return(TC_EXPORT_ERROR); + } + + + VbrControl_update_2pass_vbr_analysis(key.is_key_frame, + key.motion_bits, + key.texture_bits, + key.total_bits, + key.quantizer); + break; + //-- GMO end -- + + case 2: + // second pass of 2-pass, just a hack for the moment + + encode.quant = VbrControl_get_quant(); + encode.intra = VbrControl_get_intra(); + + if(force_key_frame) { + encode.intra=1; //key frame + force_key_frame=0; //reset + } + + if(divx5_encore(divx->handle, ENC_OPT_ENCODE_VBR, &encode, &key) < 0) { + tc_log_warn(MOD_NAME, "encoder error"); + return(TC_EXPORT_ERROR); + } + + VbrControl_update_2pass_vbr_encoding(key.motion_bits, + key.texture_bits, + key.total_bits); + break; + + default: + + if(force_key_frame) { + + encode.intra=1; //key frame + encode.quant=key.quantizer; //well defined for frames != first frame. + + if(divx5_encore(divx->handle, ENC_OPT_ENCODE_VBR, &encode, &key) < 0) { + tc_log_warn(MOD_NAME, "encoder error"); + return(TC_EXPORT_ERROR); + } + + //reset + force_key_frame=0; + + } else { + + if(divx5_encore(divx->handle, ENC_OPT_ENCODE, &encode, &key) < 0) { + tc_log_warn(MOD_NAME, "encoder error"); + return(TC_EXPORT_ERROR); + } + } + + // first pass of two-pass, save results + if(VbrMode==1) + VbrControl_update_2pass_vbr_analysis(key.is_key_frame, + key.motion_bits, + key.texture_bits, + key.total_bits, + key.quantizer); + break; + } + + // write bitstream + + /* split the AVI */ + if((uint32_t)(AVI_bytes_written(avifile)+encode.length+16+8)>>20 >= tc_avi_limit) + tc_outstream_rotate_request(); + + //0.6.2: switch outfile on "C" and -J pv + if(key.is_key_frame) tc_outstream_rotate(); + + if(AVI_write_frame(avifile, buffer, encode.length, key.is_key_frame)<0) { + tc_log_warn(MOD_NAME, "DivX avi video write error"); + return(TC_EXPORT_ERROR); + } +#endif + + return(0); + } + + if(param->flag == TC_AUDIO) return(tc_audio_encode(param->buffer, param->size, avifile)); + + // invalid flag + return(TC_EXPORT_ERROR); +} + +/* ------------------------------------------------------------ + * + * close codec + * + * ------------------------------------------------------------*/ + +MOD_close +{ + + vob_t *vob = tc_get_vob(); + if(param->flag == TC_AUDIO) return(tc_audio_close()); + + if(vob->avifile_out!=NULL) { + AVI_close(vob->avifile_out); + vob->avifile_out=NULL; + } + + if(param->flag == TC_VIDEO) return(0); + + return(TC_EXPORT_ERROR); +} + + +/* ------------------------------------------------------------ + * + * stop encoder + * + * ------------------------------------------------------------*/ + +MOD_stop +{ + + if(param->flag == TC_VIDEO) { +#if ENCORE_VERSION >= 20021024 + if(divx5_encore(encore_handle, ENC_OPT_RELEASE, NULL, NULL) < 0) { + tc_log_warn(MOD_NAME, "DivX encoder close error"); + } +#else + if(divx5_encore(divx->handle, ENC_OPT_RELEASE, NULL, NULL) < 0) { + tc_log_warn(MOD_NAME, "DivX encoder close error"); + } +#endif + + if(buffer!=NULL) { + free(buffer); + buffer=NULL; + } + + //remove codec + dlclose(handle); + +#if ENCORE_VERSION >= 20021024 +#else + switch(VbrMode) { + + case 1: + case 2: + case 3: + VbrControl_close(); + break; + + default: + break; + } +#endif + + return(0); + } + + if(param->flag == TC_AUDIO) return(tc_audio_stop()); + + return(TC_EXPORT_ERROR); +} + |
