Files
veejay/sandbox/veejay-current/tools/yuv2rawdv.c
Niels Elburg 90197d342b move stuff
git-svn-id: svn://code.dyne.org/veejay/trunk@1132 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
2008-11-01 03:31:40 +00:00

255 lines
6.6 KiB
C

/*
* yuv2rawdv - write rawdv data stream from stdin to stdout
*
* (C) Niels Elburg 2003 <nielselburg@yahoo.de>
*
* This program 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
* of the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H
#endif
#include <config.h>
#ifdef SUPPORT_READ_DV2
#include <signal.h>
#include <config.h>
#include "mjpeg_logging.h"
#include "yuv4mpeg.h"
#include <fcntl.h>
#include <libdv/dv.h>
#define NTSC_W 720
#define NTSC_H 480
#define PAL_W 720
#define PAL_H 576
#define DV_PAL_SIZE 144000
#define DV_NTSC_SIZE 120000
static int got_sigint = 0;
static int verbose = 1;
static uint8_t *yuv_in[3]; /* yuv frame from stdin */
static uint8_t *yuv422; /* yuv 4:2:2 buffer for encoding to dv */
static uint8_t *output_buf; /* buffer containing rawdv data */
static int width;
static int height;
static dv_encoder_t *encoder; /* dv decoder */
static int clamp_chroma = 0;
static int clamp_luma = 0;
static int ntsc_setup = 0;
/* convert 4:2:0 to yuv 4:2:2
derived from Kino's ExtractYUV (src/frame.cc)
*/
static void convert_yuv420p_to_yuv422() {
unsigned int x,y;
unsigned int i=0;
for(y=0; y < height; ++y) {
uint8_t *Y = yuv_in[0] + y * width;
uint8_t *Cb = yuv_in[1] + (y/2) * (width/2);
uint8_t *Cr = yuv_in[2] + (y/2) * (width/2);
for(x=0; x < width; x+=2) {
*(yuv422+i) = Y[0];
*(yuv422+i+1) = Cb[0];
*(yuv422+i+2) = Y[1];
*(yuv422+i+3) = Cr[0];
i+=4;
Y += 2;
++Cb;
++Cr;
}
}
}
/* make a yuv422 frame and give it to the DV encoder */
static void encode_yuv420_to_dv(uint8_t *outbuf) {
static uint8_t *pixels[3]; /* pointers */
time_t now = time(NULL); /* time */
convert_yuv420p_to_yuv422(); /* conversion */
pixels[0] = (uint8_t*) yuv422;
if(encoder->isPAL) {
pixels[2] = (uint8_t*)yuv422 + (PAL_W * PAL_H);
pixels[1] = (uint8_t*)yuv422 + (PAL_W * PAL_H*5)/4;
}
else {
pixels[2] = (uint8_t*)yuv422 + (NTSC_W * NTSC_H);
pixels[1] = (uint8_t*)yuv422 + (NTSC_W * NTSC_H * 5)/4;
}
dv_encode_full_frame(encoder, pixels, e_dv_color_yuv, output_buf);
dv_encode_metadata(output_buf, encoder->isPAL, encoder->is16x9, &now, 0);
dv_encode_timecode(output_buf, encoder->isPAL, 0);
}
void usage(void)
{
fprintf(stderr,
"This program reads a YUV4MPEG stream and puts RAW DV to stdout\n"
"Usage: yuv2rawdv [params]\n"
"where possible params are:\n"
" -v num Verbosity [0..2] (default 1)\n"
" -l num Clamp Luma (default 0)\n"
" -c num Clamp Chroma (default 0) \n"
);
}
void sigint_handler (int signal) {
mjpeg_debug( "Caught SIGINT, exiting...");
got_sigint = 1;
}
int main(int argc, char *argv[])
{
int frame;
int fd_in;
int fd_out;
int n;
int output_len; /* length of buffer, either 144000 or 120000 */
int bytes_written = 0;
y4m_frame_info_t frameinfo;
y4m_stream_info_t streaminfo;
while ((n = getopt(argc, argv, "v:l:c:")) != -1) {
switch (n) {
case 'v':
verbose = atoi(optarg);
if (verbose < 0 || verbose > 2) {
mjpeg_error( "-v option requires arg 0, 1, or 2");
usage();
}
break;
case 'l':
clamp_luma = atoi(optarg);
if(clamp_luma < 0 || clamp_luma > 1) {
mjpeg_error("-l option requires arg 0 or 1");
usage();
}
break;
case 'c':
clamp_chroma = atoi(optarg);
if(clamp_chroma < 0 || clamp_chroma > 1) {
mjpeg_error("-c option requires arg 0 or 1");
usage();
}
break;
default:
usage();
exit(1);
}
}
(void)mjpeg_default_handler_verbosity(verbose);
fd_in = 0; /* stdin */
fd_out = 1;
y4m_init_stream_info(&streaminfo);
y4m_init_frame_info(&frameinfo);
if (y4m_read_stream_header(fd_in, &streaminfo) != Y4M_OK) {
mjpeg_error( "Couldn't read YUV4MPEG header!");
exit (1);
}
width = y4m_si_get_width(&streaminfo);
height = y4m_si_get_height(&streaminfo);
if( height == PAL_H && width == PAL_W) {
mjpeg_info("Video is PAL, dimensions are %d x %d\n",width,height);
}
else if(height == NTSC_H && width == NTSC_W) {
mjpeg_info("Video is NTSC, dimensions are %d x %d\n", width,height);
ntsc_setup = 1;
}
else {
mjpeg_error("Error: Video is not PAL or NTSC.\n");
exit(1);
}
encoder = dv_encoder_new(ntsc_setup,clamp_luma,clamp_chroma);
encoder->isPAL = ( height == PAL_H ? 1: 0);
encoder->is16x9 = FALSE;
encoder->vlc_encode_passes = 3;
encoder->static_qno = 0;
encoder->force_dct = DV_DCT_AUTO;
if(encoder->isPAL) {
output_len = 144000; /* PAL size */
}
else {
output_len = 120000; /* NTSC size */
}
yuv_in[0] = (uint8_t*)malloc(width * height * sizeof(uint8_t));
yuv_in[1] = (uint8_t*)malloc(width * height * sizeof(uint8_t));
yuv_in[2] = (uint8_t*)malloc(width * height * sizeof(uint8_t));
yuv422 = (uint8_t*)malloc( sizeof(uint8_t) * 4 * width * height );
output_buf = (uint8_t*) malloc(sizeof(uint8_t) * output_len);
signal (SIGINT, sigint_handler);
if(verbose) {
mjpeg_info("width: %d",width);
mjpeg_info("height: %d",height);
mjpeg_info("norm: %s", (encoder->isPAL ? "PAL" : "NTSC"));
mjpeg_info("clamp luma: %s", clamp_luma ? "yes" : "no");
mjpeg_info("clamp chroma: %s", clamp_chroma ? "yes" : "no");
}
frame = 0;
while (y4m_read_frame(fd_in, &streaminfo, &frameinfo, yuv_in)==Y4M_OK && (!got_sigint)) {
encode_yuv420_to_dv(output_buf);
frame++;
bytes_written = write( fd_out, output_buf, output_len);
if(verbose) mjpeg_info ("Raw DV frame %d len = %d\r", frame,bytes_written);
if(bytes_written != output_len) {
mjpeg_warn("Unable to write Full frame. (%d out of %d bytes)\n",
bytes_written,output_len);
}
}
/* clean up */
for (n=0; n<3; n++) {
free(yuv_in[n]);
}
free(output_buf);
free(yuv422);
y4m_fini_frame_info(&frameinfo);
y4m_fini_stream_info(&streaminfo);
return 0;
}
#else
int main(int argc, char *argv[])
{
printf("yuv2rawdv needs libdv\n");
return 0;
}
#endif