You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
7.3 KiB

/*
* export_yuv4mpeg.c
*
* Copyright (C) Thomas Oestreich - June 2001
*
* 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_yuv4mpeg.so"
#define MOD_VERSION "v0.1.10 (2006-10-06)"
#define MOD_CODEC "(video) YUV4MPEG2 | (audio) MPEG/AC3/PCM"
#include "transcode.h"
#include "libtc/libtc.h"
#include "libtcvideo/tcvideo.h"
#include "aud_aux.h"
#include <stdio.h>
#include <stdlib.h>
static int verbose_flag=TC_QUIET;
static int capability_flag=TC_CAP_YUV|TC_CAP_PCM|TC_CAP_AC3|TC_CAP_AUD|TC_CAP_RGB;
#define MOD_PRE yuv4mpeg
#include "export_def.h"
#if defined(HAVE_MJPEGTOOLS_INC)
#include "yuv4mpeg.h"
#include "mpegconsts.h"
#else
#include "mjpegtools/yuv4mpeg.h"
#include "mjpegtools/mpegconsts.h"
#endif
#ifndef DAR_4_3
# define DAR_4_3 { 4, 3 }
# define DAR_16_9 { 16, 9 }
# define DAR_221_100 { 221, 100 }
# define SAR_UNKNOWN { 0, 0 }
#endif
static const y4m_ratio_t dar_4_3 = DAR_4_3;
static const y4m_ratio_t dar_16_9 = DAR_16_9;
static const y4m_ratio_t dar_221_100 = DAR_221_100;
static const y4m_ratio_t sar_UNKNOWN = SAR_UNKNOWN;
static int fd, size;
static TCVHandle tcvhandle = 0;
static ImageFormat srcfmt;
static y4m_stream_info_t y4mstream;
MOD_init
{
if (param->flag == TC_VIDEO) {
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;
}
tcvhandle = tcv_init();
if (!tcvhandle) {
tc_log_warn(MOD_NAME, "image conversion init failed");
return TC_EXPORT_ERROR;
}
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_flag);
}
return TC_EXPORT_ERROR;
}
static void asrcode2asrratio(int asr, y4m_ratio_t *r)
{
switch (asr) {
case 2: *r = dar_4_3; break;
case 3: *r = dar_16_9; break;
case 4: *r = dar_221_100; break;
case 1: r->n = 1; r->d = 1; break;
case 0: default: *r = sar_UNKNOWN; break;
}
}
MOD_open
{
if (param->flag == TC_VIDEO) {
int asr, ret;
// char dar_tag[20];
y4m_ratio_t framerate;
y4m_ratio_t asr_rate;
//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);
if (framerate.n == 0 && framerate.d == 0) {
framerate.n = vob->ex_fps*1000;
framerate.d = 1000;
}
asr = (vob->ex_asr<0) ?vob->im_asr :vob->ex_asr;
asrcode2asrratio(asr, &asr_rate);
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, asr_rate));
/*
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);
y4m_si_set_chroma(&y4mstream, Y4M_CHROMA_420JPEG); // XXX
size = vob->ex_v_width * vob->ex_v_height * 3/2;
fd = open(vob->video_out_file, O_RDWR|O_CREAT|O_TRUNC,
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
if (fd < 0) {
tc_log_perror(MOD_NAME, "open file");
return(TC_EXPORT_ERROR);
}
ret = y4m_write_stream_header(fd, &y4mstream);
if (ret != Y4M_OK){
tc_log_error(MOD_NAME, "write stream header (err=%i)", ret);
tc_log_perror(MOD_NAME, "error");
return(TC_EXPORT_ERROR);
}
return TC_EXPORT_OK;
}
if (param->flag == TC_AUDIO) {
return tc_audio_open(vob, NULL);
}
return TC_EXPORT_ERROR;
}
MOD_encode
{
if (param->flag == TC_VIDEO) {
vob_t *vob = tc_get_vob();
y4m_frame_info_t info;
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;
}
#ifdef USE_NEW_MJPEGTOOLS_CODE
y4m_init_frame_info(&info);
if (y4m_write_frame_header(fd, &y4mstream, &info) != Y4M_OK) {
tc_log_perror(MOD_NAME, "write frame header");
return TC_EXPORT_ERROR;
}
#else
y4m_init_frame_info(&info);
if(y4m_write_frame_header(fd, &info) != Y4M_OK) {
tc_log_perror(MOD_NAME, "write frame header");
return TC_EXPORT_ERROR;
}
#endif
/*
* do not trust param->size
* -- Looks like there is an outdated comment,
* a latent issue or both FR
*/
if (tc_pwrite(fd, param->buffer, size) != size) {
tc_log_perror(MOD_NAME, "write frame");
return TC_EXPORT_ERROR;
}
return TC_EXPORT_OK;
}
if (param->flag == TC_AUDIO) {
return tc_audio_encode(param->buffer, param->size, NULL);
}
return TC_EXPORT_ERROR;
}
MOD_stop
{
if (param->flag == TC_VIDEO) {
return TC_EXPORT_OK;
}
if (param->flag == TC_AUDIO) {
return tc_audio_stop();
}
return TC_EXPORT_ERROR;
}
MOD_close
{
if (param->flag == TC_VIDEO) {
tcv_free(tcvhandle);
close(fd);
return TC_EXPORT_OK;
}
if (param->flag == TC_AUDIO) {
return tc_audio_close();
}
return TC_EXPORT_ERROR;
}
/*************************************************************************/
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/