diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/export/export_mpeg2enc.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/export/export_mpeg2enc.c | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/export/export_mpeg2enc.c b/debian/transcode/transcode-1.1.7/export/export_mpeg2enc.c new file mode 100644 index 00000000..3603387b --- /dev/null +++ b/debian/transcode/transcode-1.1.7/export/export_mpeg2enc.c @@ -0,0 +1,468 @@ +/* + * export_mpeg2enc.c + * + * Copyright (C) Gerhard Monzel - January 2002 + * + * 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. + * + */ + +#define MOD_NAME "export_mpeg2enc.so" +#define MOD_VERSION "v1.1.10 (2003-10-30)" +#define MOD_CODEC "(video) MPEG 1/2" + +#include "transcode.h" +#include "libtcvideo/tcvideo.h" + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> + +#if defined(HAVE_MJPEGTOOLS_INC) +#include "yuv4mpeg.h" +#include "mpegconsts.h" +#else +#include "mjpegtools/yuv4mpeg.h" +#include "mjpegtools/mpegconsts.h" +#endif + +static int verbose_flag=TC_QUIET; +static int capability_flag=TC_CAP_YUV|TC_CAP_RGB; + +#define MOD_PRE mpeg2enc +#include "export_def.h" + +static y4m_stream_info_t y4mstream; + +static FILE *sa_ip = NULL; +static int sa_width = 0; +static int sa_height = 0; +static int sa_size_l = 0; +static int sa_size_c = 0; +static TCVHandle tcvhandle = 0; +static ImageFormat srcfmt; + +#define Y4M_LINE_MAX 256 +#define Y4M_MAGIC "YUV4MPEG2" +#define Y4M_FRAME_MAGIC "FRAME" + + +static int y4m_snprint_xtags(char *s, int maxn, y4m_xtag_list_t *xtags) +{ + int i, room; + + for (i = 0, room = maxn - 1; i < y4m_xtag_count(xtags); i++) { + int n = tc_snprintf(s, room + 1, " %s", y4m_xtag_get(xtags, i)); + if ((n < 0) || (n > room)) return Y4M_ERR_HEADER; + s += n; + room -= n; + } + s[0] = '\n'; /* finish off header with newline */ + s[1] = '\0'; /* ...and end-of-string */ + return Y4M_OK; +} + +static int y4m_write_stream_header2(FILE *fd, y4m_stream_info_t *i) +{ + char s[Y4M_LINE_MAX+1]; + int n; + int err; + + y4m_ratio_t tmpframerate = y4m_si_get_framerate(i); + y4m_ratio_t tmpsamplerate = y4m_si_get_sampleaspect(i); + y4m_ratio_reduce(&tmpframerate); + y4m_ratio_reduce(&tmpsamplerate); + n = tc_snprintf(s, sizeof(s), "%s W%d H%d F%d:%d I%s A%d:%d", + Y4M_MAGIC, + y4m_si_get_width(i), + y4m_si_get_height(i), + y4m_si_get_framerate(i).n, y4m_si_get_framerate(i).d, + (y4m_si_get_interlace(i) == Y4M_ILACE_NONE) ? "p" : + (y4m_si_get_interlace(i) == Y4M_ILACE_TOP_FIRST) ? "t" : + (y4m_si_get_interlace(i) == Y4M_ILACE_BOTTOM_FIRST) ? "b" : "?", + y4m_si_get_sampleaspect(i).n, y4m_si_get_sampleaspect(i).d); + if (n < 0) return Y4M_ERR_HEADER; + if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, y4m_si_xtags(i))) + != Y4M_OK) + return err; + /* zero on error */ + return (fwrite(s, strlen(s), 1, fd) ? Y4M_OK : Y4M_ERR_SYSTEM); + +} + +static int y4m_write_frame_header2(FILE *fd, y4m_frame_info_t *i) +{ + char s[Y4M_LINE_MAX+1]; + int n; + int err; + + n = snprintf(s, sizeof(s), "%s", Y4M_FRAME_MAGIC); + if (n < 0) return Y4M_ERR_HEADER; + if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, y4m_fi_xtags(i))) + != Y4M_OK) + return err; + /* zero on error */ + return (fwrite(s, strlen(s), 1, fd) ? Y4M_OK : Y4M_ERR_SYSTEM); +} + + +/* ------------------------------------------------------------ + * + * open outputfile + * + * ------------------------------------------------------------*/ + + +MOD_open +{ + + int verb, prof=0; + const char *p1, *p2, *p3, *p4; + char bitrate[25]; + //char dar_tag[20]; + y4m_ratio_t framerate; + y4m_ratio_t dar; + int frc=0, asr=0; + char *tv_type="-n p"; + char *pulldown=""; + int fields = (vob->encode_fields == TC_ENCODE_FIELDS_TOP_FIRST + || vob->encode_fields == TC_ENCODE_FIELDS_BOTTOM_FIRST); + + /* check for mpeg2enc */ + if (tc_test_program("mpeg2enc") != 0) return (TC_EXPORT_ERROR); + + if(param->flag == TC_VIDEO) + { + char buf[PATH_MAX]; + char buf2[16]; + + //note: this is the real framerate of the raw stream + framerate = (vob->ex_frc==0) ? mpeg_conform_framerate(vob->ex_fps):mpeg_framerate(vob->ex_frc); + asr = (vob->ex_asr<0) ? vob->im_asr:vob->ex_asr; + switch (asr) { + case 1: dar.n = 1; dar.d = 1; break; + case 2: dar = y4m_dar_4_3; break; + case 3: dar = y4m_dar_16_9; break; + case 4: dar = y4m_dar_221_100; break; + case 0: default: dar.n=0; dar.d=0; break; + } + + y4m_init_stream_info(&y4mstream); + y4m_si_set_framerate(&y4mstream,framerate); + if (vob->encode_fields == TC_ENCODE_FIELDS_TOP_FIRST) { + y4m_si_set_interlace(&y4mstream, Y4M_ILACE_TOP_FIRST); + } else if (vob->encode_fields == TC_ENCODE_FIELDS_BOTTOM_FIRST) { + y4m_si_set_interlace(&y4mstream, Y4M_ILACE_BOTTOM_FIRST); + } else if (vob->encode_fields == TC_ENCODE_FIELDS_PROGRESSIVE) { + y4m_si_set_interlace(&y4mstream, Y4M_ILACE_NONE); + } + y4m_si_set_sampleaspect(&y4mstream, y4m_guess_sar(vob->ex_v_width, vob->ex_v_height, dar)); + /* + tc_snprintf( dar_tag, 19, "XM2AR%03d", asr ); + y4m_xtag_add( y4m_si_xtags(&y4mstream), dar_tag ); + */ + y4m_si_set_height(&y4mstream, vob->ex_v_height); + y4m_si_set_width(&y4mstream, vob->ex_v_width); + + verb = (verbose & TC_DEBUG) ? 2:0; + + //base profile support and coustom setting + //-- -F "<base-profile>[,<options_string>]" + //-- parameter 1 (base profile) -- + + p1 = vob->ex_v_fcc; + p2 = vob->ex_a_fcc; + p3 = vob->ex_profile_name; //unsupported + + if(verbose_flag & TC_DEBUG) tc_log_info(MOD_NAME, "P1=%s, P2=%s, P3=%s", p1, p2, p3); + + prof = (p1==NULL || strlen(p1) == 0) ? 0:atoi(p1); + + + //-- adjust frame rate stuff -- + //----------------------------- + if (vob->ex_frc) { // use specified output frame rate code + frc = vob->ex_frc; + } else { // otherwise we guess based on the frame rate + if ((int)(vob->ex_fps*100.0 + 0.01) == (int)(29.97*100.0)) { + frc=4; + } else if ((int)(vob->ex_fps*100.0 + 0.01) == (int)(23.97*100.0)) { + frc=1; + } else if ((int)(vob->ex_fps*100.0 + 0.01) == (int)(24.00*100.0)) { + frc=2; + } else { + frc=3; // default is PAL framerate code + } + } + // now set the stream type to either NTSC or PAL based on the + // frame rate code + if ((frc == 4) || (frc == 1) || (frc == 2)) { + tv_type = "-n n"; + } else { + tv_type = "-n p"; // default is PAL + } + + //ThOe pulldown? + if(vob->pulldown) pulldown="-p"; + + //ThOe collect additional parameter + if(asr>0) + tc_snprintf(buf2, sizeof(buf2), "%s %s -a %d", tv_type, pulldown, asr); + else + tc_snprintf(buf2, sizeof(buf2), "%s %s", tv_type, pulldown); + + if (p2==NULL) p2=""; + + // additional commandline arguments + if (vob->ex_v_string==NULL) p4=""; + else p4=vob->ex_v_string; + + // constant quantizer encoding? + if (vob->divxmultipass == 3) { + if (vob->video_max_bitrate != 0) { + tc_snprintf(bitrate, sizeof(bitrate), "-q %d -b %d", vob->divxbitrate, vob->video_max_bitrate); + } else { + tc_snprintf(bitrate, sizeof(bitrate), "-q %d", vob->divxbitrate); + } + } else { + tc_snprintf(bitrate, sizeof(bitrate), "-b %d", vob->divxbitrate); + } + + + switch(prof) { + + case 1: + + //Standard VCD. An MPEG1 profile + //exactly to the VCD2.0 specification. + + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d -f 1 -F %d %s %s -o \"%s\" %s", verb, fields, frc, buf2, p4, vob->video_out_file, p2); + break; + + case 2: + + //User VCD + + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d -q 3 -f 2 -4 2 -2 3 %s -F %d %s -o \"%s\" %s %s", verb, fields, bitrate, frc, buf2, vob->video_out_file, p2, p4); + break; + + case 3: + + //Generic MPEG2 + + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d -q 3 -f 3 -4 2 -2 3 %s -s -F %d %s -o \"%s\" %s %s", verb, fields, bitrate, frc, buf2, vob->video_out_file, p2, p4); + break; + + case 4: + + //Standard SVCD. An MPEG-2 profile + //exactly to the SVCD2.0 specification + + if ( !(vob->export_attributes & TC_EXPORT_ATTRIBUTE_VBITRATE) ) + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d -f 4 -F %d %s -o \"%s\" %s %s", verb, fields, frc, buf2, vob->video_out_file, p2, p4); + else + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d -f 4 %s -F %d %s -o \"%s\" %s %s", verb, fields, bitrate, frc, buf2, vob->video_out_file, p2, p4); + break; + + case 5: + + //User SVCD + + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d -q 3 -f 5 -4 2 -2 3 %s -F %d %s -V 230 -o \"%s\" %s %s", verb, fields, bitrate, frc, buf2, vob->video_out_file, p2, p4); + break; + + case 6: + + // Manual parameter mode. + + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d %s -o \"%s\" %s %s", verb, fields, bitrate, vob->video_out_file, p2?p2:"", p4); + break; + + case 8: + + //DVD + + if ( !(vob->export_attributes & TC_EXPORT_ATTRIBUTE_VBITRATE) ) + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d -f 8 -F %d %s -o \"%s\" %s %s", verb, fields, frc, buf2, vob->video_out_file, p2, p4); + else + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d -f 8 %s -F %d %s -o \"%s\" %s %s", verb, fields, bitrate, frc, buf2, vob->video_out_file, p2, p4); + + break; + + + case 0: + default: + + //Generic MPEG1 + + tc_snprintf(buf, sizeof(buf), "mpeg2enc -v %d -I %d -q 3 -f 0 -4 2 -2 3 %s -F %d %s -o \"%s\" %s %s", verb, fields, bitrate, frc, buf2, vob->video_out_file, p2, p4); + break; + } + + tc_log_info(MOD_NAME, "%s", buf); + + sa_ip = popen(buf, "w"); + if (!sa_ip) return(TC_EXPORT_ERROR); + + if( y4m_write_stream_header2( sa_ip, &y4mstream ) != Y4M_OK ){ + tc_log_perror(MOD_NAME, "write stream header"); + return(TC_EXPORT_ERROR); + } + + // tc_snprintf(buf, sizeof(buf), MENC_HDR, sa_width, sa_height); + //fwrite(buf, strlen(buf), 1, sa_ip); + + return(0); + } + + if(param->flag == TC_AUDIO) return(0); + + // invalid flag + return(TC_EXPORT_ERROR); +} + + +/* ------------------------------------------------------------ + * + * init codec + * + * ------------------------------------------------------------*/ + +MOD_init +{ + + if(param->flag == TC_VIDEO) + { + int prof = 0; + + sa_width = vob->ex_v_width; + sa_height = vob->ex_v_height; + sa_size_l = sa_width * sa_height; + sa_size_c = sa_size_l/4; + + if (vob->im_v_codec == CODEC_YUV) { + srcfmt = IMG_YUV_DEFAULT; + } else if (vob->im_v_codec == CODEC_YUV422) { + srcfmt = IMG_YUV422P; + } else if (vob->im_v_codec == CODEC_RGB) { + srcfmt = IMG_RGB_DEFAULT; + } else { + tc_log_warn(MOD_NAME, "unsupported video format %d", + vob->im_v_codec); + return(TC_EXPORT_ERROR); + } + if (!(tcvhandle = tcv_init())) { + tc_log_warn(MOD_NAME, "image conversion init failed"); + return(TC_EXPORT_ERROR); + } + + if (vob->ex_v_fcc) prof = atoi(vob->ex_v_fcc); + + return(0); + } + + if(param->flag == TC_AUDIO) return(0); + + // invalid flag + return(TC_EXPORT_ERROR); +} + +/* ------------------------------------------------------------ + * + * encode and export frame + * + * ------------------------------------------------------------*/ + + +MOD_encode +{ + y4m_frame_info_t info; + + if(param->flag == TC_VIDEO) + { + vob_t *vob = tc_get_vob(); + + if (!tcv_convert(tcvhandle, param->buffer, param->buffer, + vob->ex_v_width, vob->ex_v_height, + srcfmt, IMG_YUV420P)) { + tc_log_warn(MOD_NAME, "image format conversion failed"); + return(TC_EXPORT_ERROR); + } + + y4m_init_frame_info(&info); + + if( y4m_write_frame_header2( sa_ip, &info ) != Y4M_OK ){ + tc_log_perror(MOD_NAME, "write stream header"); + return(TC_EXPORT_ERROR); + } + + fwrite(param->buffer, sa_size_l, 1, sa_ip); + fwrite(param->buffer + sa_size_l, sa_size_c, 1, sa_ip); + fwrite(param->buffer + sa_size_l + sa_size_c, sa_size_c, 1, sa_ip); + + return (0); + } + + if(param->flag == TC_AUDIO) return(0); + + // invalid flag + return(TC_EXPORT_ERROR); +} + +/* ------------------------------------------------------------ + * + * stop encoder + * + * ------------------------------------------------------------*/ + +MOD_stop +{ + if(param->flag == TC_VIDEO) { + return (0); + } + + if(param->flag == TC_AUDIO) return (0); + return(TC_EXPORT_ERROR); +} + +/* ------------------------------------------------------------ + * + * close codec + * + * ------------------------------------------------------------*/ + +MOD_close +{ + + if(param->flag == TC_AUDIO) return (0); + + if(param->flag == TC_VIDEO) + { + if (sa_ip) pclose(sa_ip); + sa_ip = NULL; + + tcv_free(tcvhandle); + tcvhandle = 0; + + return(0); + } + + return(TC_EXPORT_ERROR); +} + |
