Files
veejay/veejay-ng/vevosample/vj-yuv4mpeg.c
Niels Elburg 961cc560f5 replaced malloc for vj_malloc, added assertion in malloc function for debugging purposes
git-svn-id: svn://code.dyne.org/veejay/trunk@596 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
2006-09-03 19:07:33 +00:00

254 lines
6.2 KiB
C

/*
* Linux VeeJay
*
* Copyright(C)2002-2004 Niels Elburg <nelburg@looze.net>
*
* 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
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <libvjmsg/vj-common.h>
#include <vevosample/vj-yuv4mpeg.h>
#include <vevosample/defs.h>
#include <string.h>
/* see vj-v4lvideo for details about structure */
#include <mjpegtools/mpegconsts.h>
#include <libvjmem/vjmem.h>
typedef struct {
y4m_stream_info_t streaminfo;
y4m_frame_info_t frameinfo;
y4m_ratio_t sar;
y4m_ratio_t dar;
int width;
int height;
int fd;
float video_fps;
int sar_w;
int sar_h;
} vj_yuv;
int bytecount = 0;
void *vj_yuv4mpeg_alloc(float fps, int w, int h, int sar_w, int sar_h)
{
vj_yuv *yuv4mpeg = (void *) vj_malloc(sizeof(vj_yuv));
if(!yuv4mpeg) return NULL;
yuv4mpeg->sar = y4m_sar_UNKNOWN;
yuv4mpeg->dar = y4m_dar_4_3;
y4m_init_stream_info(&(yuv4mpeg->streaminfo));
y4m_init_frame_info(&(yuv4mpeg->frameinfo));
yuv4mpeg->width = w;
yuv4mpeg->height = h;
yuv4mpeg->video_fps = fps;
yuv4mpeg->sar_w = sar_w;
yuv4mpeg->sar_h = sar_h;
return (void*)yuv4mpeg;
}
void vj_yuv4mpeg_free(void *v) {
}
int vj_yuv_stream_start_read(void *data, char *filename, int width,
int height)
{
int i, w, h;
vj_yuv *yuv4mpeg = (vj_yuv*) data;
yuv4mpeg->fd = open(filename,O_RDONLY);
if (!yuv4mpeg->fd) {
veejay_msg(VEEJAY_MSG_ERROR, "Unable to open video stream %s\n",
filename);
return -1;
}
i = y4m_read_stream_header(yuv4mpeg->fd, &(yuv4mpeg->streaminfo));
if (i != Y4M_OK) {
veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg: %s", y4m_strerr(i));
return -1;
}
w = y4m_si_get_width(&(yuv4mpeg->streaminfo));
h = y4m_si_get_height(&(yuv4mpeg->streaminfo));
if( w != width || h != height )
{
veejay_msg(VEEJAY_MSG_ERROR,
"Video dimensions: %d x %d must match %d x %d. Stream cannot be opened", w, h,
width, height);
return -1;
}
veejay_msg(VEEJAY_MSG_DEBUG, "YUV4MPEG: stream header ok");
return 0;
}
int vj_yuv_stream_write_header(void * data)
{
vj_yuv *yuv4mpeg = (vj_yuv*) data;
int i = 0;
y4m_si_set_width(&(yuv4mpeg->streaminfo), yuv4mpeg->width);
y4m_si_set_height(&(yuv4mpeg->streaminfo), yuv4mpeg->height);
y4m_si_set_interlace(&(yuv4mpeg->streaminfo), 0);
y4m_si_set_framerate(&(yuv4mpeg->streaminfo),
mpeg_conform_framerate(yuv4mpeg->video_fps));
if (!Y4M_RATIO_EQL(yuv4mpeg->sar, y4m_sar_UNKNOWN)) {
y4m_si_set_sampleaspect(&(yuv4mpeg->streaminfo), yuv4mpeg->sar);
yuv4mpeg->sar.n = yuv4mpeg->sar_w;
yuv4mpeg->sar.d = yuv4mpeg->sar_h;
y4m_si_set_sampleaspect(&(yuv4mpeg->streaminfo), yuv4mpeg->sar);
} else {
y4m_ratio_t dar2 = y4m_guess_sar(yuv4mpeg->width,
yuv4mpeg->height,
yuv4mpeg->dar);
y4m_si_set_sampleaspect(&(yuv4mpeg->streaminfo), dar2);
}
i = y4m_write_stream_header(yuv4mpeg->fd, &(yuv4mpeg->streaminfo));
if (i != Y4M_OK)
return -1;
y4m_log_stream_info(LOG_INFO, "vj-yuv4mpeg", &(yuv4mpeg->streaminfo));
return 0;
}
int vj_yuv_stream_open_pipe(void *data, char *filename)
{
vj_yuv *yuv4mpeg = (vj_yuv*) data;
yuv4mpeg->fd = open(filename,O_WRONLY,0600);
if(!yuv4mpeg->fd) return 0;
return 1;
}
int vj_yuv_stream_header_pipe(void *data)
{
vj_yuv *yuv4mpeg = (vj_yuv*) data;
vj_yuv_stream_write_header(yuv4mpeg);
return 1;
}
int vj_yuv_stream_start_write(void *data, char *filename)
{
vj_yuv *yuv4mpeg = (vj_yuv*) data;
struct stat sstat;
if(strncasecmp( filename, "stdout", 6) == 0)
{
yuv4mpeg->fd = 1;
}
else
{
if(strncasecmp(filename, "stderr", 6) == 0)
{
yuv4mpeg->fd = 2;
}
else
{
if (stat(filename, &sstat) == 0)
{
if (S_ISREG(sstat.st_mode))
{
/* the file is a regular file */
yuv4mpeg->fd = open(filename, O_APPEND | O_WRONLY, 0600);
if (!yuv4mpeg->fd)
return -1;
}
else
{
if (S_ISFIFO(sstat.st_mode))
veejay_msg(VEEJAY_MSG_INFO, "Destination file is a FIFO");
return 1; // pipe needs handling
}
}
else
{
veejay_msg(VEEJAY_MSG_INFO, "Creating YUV4MPEG regular file %s\n",
filename);
yuv4mpeg->fd = open(filename, O_CREAT | O_WRONLY, 0600);
if (!yuv4mpeg->fd)
return -1;
}
}
}
vj_yuv_stream_write_header(yuv4mpeg);
return 0;
}
void vj_yuv_stream_stop_write(void *data)
{
vj_yuv *yuv4mpeg = (vj_yuv*) data;
y4m_fini_stream_info(&(yuv4mpeg->streaminfo));
y4m_fini_frame_info(&(yuv4mpeg->frameinfo));
close(yuv4mpeg->fd);
}
void vj_yuv_stream_stop_read(void *data)
{
vj_yuv *yuv4mpeg = (vj_yuv*) data;
y4m_fini_stream_info(&(yuv4mpeg->streaminfo));
y4m_fini_frame_info(&(yuv4mpeg->frameinfo));
close(yuv4mpeg->fd);
yuv4mpeg->sar = y4m_sar_UNKNOWN;
yuv4mpeg->dar = y4m_dar_4_3;
}
int vj_yuv_get_frame(void *data, uint8_t * dst[3])
{
int i;
vj_yuv *yuv4mpeg = (vj_yuv*) data;
i = y4m_read_frame(yuv4mpeg->fd, &(yuv4mpeg->streaminfo),
&(yuv4mpeg->frameinfo), dst);
if (i != Y4M_OK)
{
veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg %s", y4m_strerr(i));
return -1;
}
return 0;
}
int vj_yuv_put_frame(void *data, uint8_t ** src)
{
vj_yuv *yuv4mpeg = (vj_yuv*) data;
int i;
if (!yuv4mpeg->fd) {
veejay_msg(VEEJAY_MSG_ERROR, "Invalid file descriptor for y4m stream");
return -1;
}
i = y4m_write_frame(yuv4mpeg->fd, &(yuv4mpeg->streaminfo),
&(yuv4mpeg->frameinfo), src);
if (i != Y4M_OK) {
veejay_msg(VEEJAY_MSG_ERROR, "Yuv4Mpeg : [%s]", y4m_strerr(i));
return -1;
}
return 0;
}