encoders yuv planar formats,lossless jpeg,lossless huffyuv, mjpeg, mjpegb, divx , mpeg4,dv, tested recording features

git-svn-id: svn://code.dyne.org/veejay/trunk@588 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
This commit is contained in:
Niels Elburg
2006-08-14 17:13:51 +00:00
parent abf9d41c1c
commit b1912ad175
12 changed files with 611 additions and 557 deletions

View File

@@ -762,6 +762,8 @@ avi_t *AVI_open_input_file(char *filename, int getIndex, int mmap_size)
AVI->video_strn = num_stream; AVI->video_strn = num_stream;
vids_strh_seen = 1; vids_strh_seen = 1;
veejay_msg(0, "Try '%s'", AVI->compressor );
/* setup FFMPEG codec */ /* setup FFMPEG codec */
if( strncasecmp("mjpg", AVI->compressor, 4) == 0) if( strncasecmp("mjpg", AVI->compressor, 4) == 0)
AVI->ffmpeg_codec_id = CODEC_ID_MJPEG; AVI->ffmpeg_codec_id = CODEC_ID_MJPEG;
@@ -778,6 +780,11 @@ avi_t *AVI_open_input_file(char *filename, int getIndex, int mmap_size)
if( strncasecmp("div3", AVI->compressor,4) == 0) if( strncasecmp("div3", AVI->compressor,4) == 0)
AVI->ffmpeg_codec_id = CODEC_ID_MSMPEG4V3; AVI->ffmpeg_codec_id = CODEC_ID_MSMPEG4V3;
if( strncasecmp("ljpg", AVI->compressor,4 ) == 0 )
AVI->ffmpeg_codec_id = CODEC_ID_LJPEG;
if( strncasecmp("hfyu", AVI->compressor,4 ) == 0 )
AVI->ffmpeg_codec_id = CODEC_ID_HUFFYUV;
/* non standard follow */ /* non standard follow */
if( strncasecmp("iyuv", AVI->compressor,4) == 0) if( strncasecmp("iyuv", AVI->compressor,4) == 0)
AVI->ffmpeg_codec_id = 997; AVI->ffmpeg_codec_id = 997;

View File

@@ -34,9 +34,7 @@
#include <libel/lav_io.h> #include <libel/lav_io.h>
//#include <veejay/vj-lib.h> //#include <veejay/vj-lib.h>
#include <libvjmsg/vj-common.h> #include <libvjmsg/vj-common.h>
#ifdef USE_GDK_PIXBUF
#include <libel/pixbuf.h>
#endif
extern int AVI_errno; extern int AVI_errno;
static int _lav_io_default_chroma = CHROMAUNKNOWN; static int _lav_io_default_chroma = CHROMAUNKNOWN;
static char video_format=' '; static char video_format=' ';
@@ -260,6 +258,7 @@ int lav_query_polarity(char format)
case 'D': return LAV_NOT_INTERLACED; //divx case 'D': return LAV_NOT_INTERLACED; //divx
case 'Y': return LAV_NOT_INTERLACED; // planar yuv 4:2:0 (yv12) case 'Y': return LAV_NOT_INTERLACED; // planar yuv 4:2:0 (yv12)
case 'P': return LAV_NOT_INTERLACED; // planar yuv 4:2:2 (yv16) case 'P': return LAV_NOT_INTERLACED; // planar yuv 4:2:2 (yv16)
case 'Q': return LAV_NOT_INTERLACED;
case 'M': return LAV_NOT_INTERLACED; // mpeg4 , case 'M': return LAV_NOT_INTERLACED; // mpeg4 ,
case 'd': return LAV_INTER_BOTTOM_FIRST; // DV, interlaced case 'd': return LAV_INTER_BOTTOM_FIRST; // DV, interlaced
case 'j': return LAV_INTER_TOP_FIRST; case 'j': return LAV_INTER_TOP_FIRST;
@@ -282,10 +281,46 @@ lav_file_t *lav_open_output_file(char *filename, char format,
int width, int height, int interlaced, double fps, int width, int height, int interlaced, double fps,
int asize, int achans, long arate) int asize, int achans, long arate)
{ {
char fourcc[5];
int is_avi = 1;
switch(format)
{
case 'a': // mjpeg
sprintf(fourcc,"%s", "mjpg" ); break;
case 'd': // digital video
sprintf(fourcc,"%s", "dvsd" ); break;
case 'D': // divx
sprintf(fourcc, "%s", "div3"); break;
case 'L': //lossless
sprintf(fourcc, "%s", "ljpg"); break;
case 'A': //mjpegB
sprintf(fourcc, "%s", "mjpa"); break;
case 'H': //huffyuv
sprintf(fourcc, "%s", "hfyu"); break;
case 'M': //mpeg4
sprintf(fourcc, "%s", "MP4V" ); break;
case 'P': //yuv422 planar
sprintf(fourcc, "%s", "YV16") ; break;
case 'Y': //yuv420 planar
sprintf(fourcc, "%s", "IYUV") ; break;
case 'Q': //yuv444 planar
sprintf(fourcc, "%s", "i444") ; break;
case 'b':
sprintf(fourcc, "%s", "dvsd") ;
// is_avi = 0;
break;
default:
veejay_msg(0,
"Invalid format");
return NULL;
break;
}
lav_file_t *lav_fd = (lav_file_t*) malloc(sizeof(lav_file_t)); lav_file_t *lav_fd = (lav_file_t*) malloc(sizeof(lav_file_t));
if(lav_fd==0) { internal_error=ERROR_MALLOC; return 0; } if(lav_fd==0) { internal_error=ERROR_MALLOC; return 0; }
/* Set lav_fd */ /* Set lav_fd */
lav_fd->avi_fd = 0; lav_fd->avi_fd = 0;
@@ -297,72 +332,29 @@ lav_file_t *lav_open_output_file(char *filename, char format,
lav_fd->is_MJPG = 1; lav_fd->is_MJPG = 1;
lav_fd->MJPG_chroma = _lav_io_default_chroma; lav_fd->MJPG_chroma = _lav_io_default_chroma;
switch(format) if( is_avi )
{ lav_fd->avi_fd = AVI_open_output_file(filename);
case 'a':
case 'A':
/* Open AVI output file */
lav_fd->avi_fd = AVI_open_output_file(filename); if(!lav_fd->avi_fd) { free(lav_fd); return 0; }
if(!lav_fd->avi_fd) { free(lav_fd); return 0; }
AVI_set_video(lav_fd->avi_fd, width, height, fps, "MJPG"); AVI_set_video(lav_fd->avi_fd, width, height, fps, fourcc);
if (asize) AVI_set_audio(lav_fd->avi_fd, achans, arate, asize, WAVE_FORMAT_PCM);
return lav_fd; if (asize) AVI_set_audio(lav_fd->avi_fd, achans, arate, asize, WAVE_FORMAT_PCM);
break;
case 'Y': return lav_fd;
lav_fd->avi_fd = AVI_open_output_file(filename);
if(!lav_fd->avi_fd) { free(lav_fd); return 0; }
AVI_set_video(lav_fd->avi_fd, width,height,fps, "iyuv");
if(asize) AVI_set_audio(lav_fd->avi_fd, achans,arate,asize,WAVE_FORMAT_PCM);
return lav_fd;
break;
case 'P':
lav_fd->avi_fd = AVI_open_output_file(filename);
if(!lav_fd->avi_fd) { free(lav_fd); return 0; }
AVI_set_video(lav_fd->avi_fd, width,height,fps, "yv16");
if(asize) AVI_set_audio(lav_fd->avi_fd, achans,arate,asize,WAVE_FORMAT_PCM);
return lav_fd;
break;
case 'D':
lav_fd->avi_fd = AVI_open_output_file(filename);
if(!lav_fd->avi_fd) { free(lav_fd); return 0; }
AVI_set_video(lav_fd->avi_fd,width,height,fps, "div3");
if(asize) AVI_set_audio(lav_fd->avi_fd,achans,arate,asize,WAVE_FORMAT_PCM);
return lav_fd;
case 'M':
lav_fd->avi_fd = AVI_open_output_file(filename);
if(!lav_fd->avi_fd) { free(lav_fd); return 0; }
AVI_set_video(lav_fd->avi_fd,width,height,fps, "mp4v");
if(asize) AVI_set_audio(lav_fd->avi_fd,achans,arate,asize,WAVE_FORMAT_PCM);
return lav_fd;
case 'b':
case 'd':
lav_fd->avi_fd = AVI_open_output_file(filename);
if(!lav_fd->avi_fd) { free(lav_fd); return 0; }
AVI_set_video(lav_fd->avi_fd,width,height,fps, "dvsd");
if(asize) AVI_set_audio(lav_fd->avi_fd,achans,arate,asize,WAVE_FORMAT_PCM);
return lav_fd;
}
if(lav_fd) free(lav_fd);
return NULL;
} }
int lav_close(lav_file_t *lav_file) int lav_close(lav_file_t *lav_file)
{ {
int ret = 0; int ret = 0;
video_format = lav_file->format; internal_error = 0; /* for error messages */ video_format = lav_file->format; internal_error = 0; /* for error messages */
switch(video_format) switch(video_format)
{ {
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
case 'b': case 'b':
ret = rawdv_close(lav_file->dv_fd); ret = rawdv_close(lav_file->dv_fd);
break; break;
#endif
#ifdef USE_GDK_PIXBUF
case 'x':
vj_picture_cleanup( lav_file->picture );
ret = 1;
break;
#endif #endif
default: default:
ret = AVI_close(lav_file->avi_fd); ret = AVI_close(lav_file->avi_fd);
@@ -381,16 +373,10 @@ int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count)
long jpglen = 0; long jpglen = 0;
video_format = lav_file->format; internal_error = 0; /* for error messages */ video_format = lav_file->format; internal_error = 0; /* for error messages */
#ifdef SUPPORT_READ_DV2
if(video_format == 'b')
return -1;
#endif
/* For interlaced video insert the apropriate APPn markers */ /* For interlaced video insert the apropriate APPn markers */
#ifdef USE_GDK_PIXBUF
if(video_format == 'x') if(lav_file->interlacing!=LAV_NOT_INTERLACED && (lav_file->format == 'a' || lav_file->format=='A' ||
return -1; lav_file->format == 'L'))
#endif
if(lav_file->interlacing!=LAV_NOT_INTERLACED && (lav_file->format == 'a' || lav_file->format=='A'))
{ {
jpgdata = buff; jpgdata = buff;
jpglen = size; jpglen = size;
@@ -420,8 +406,8 @@ int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count)
/* Update pointer and len for second field */ /* Update pointer and len for second field */
jpgdata += jpeg_padded_len; jpgdata += jpeg_padded_len;
jpglen -= jpeg_padded_len; jpglen -= jpeg_padded_len;
} }
} }
res = 0; /* Silence gcc */ res = 0; /* Silence gcc */
for(n=0;n<count;n++) for(n=0;n<count;n++)
@@ -439,11 +425,7 @@ int lav_write_audio(lav_file_t *lav_file, uint8_t *buff, long samps)
video_format = lav_file->format; internal_error = 0; /* for error messages */ video_format = lav_file->format; internal_error = 0; /* for error messages */
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return 0; return 0;
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 0;
#endif #endif
return AVI_write_audio( lav_file->avi_fd, buff, samps*lav_file->bps); return AVI_write_audio( lav_file->avi_fd, buff, samps*lav_file->bps);
} }
@@ -456,10 +438,6 @@ long lav_video_frames(lav_file_t *lav_file)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_video_frames(lav_file->dv_fd); return rawdv_video_frames(lav_file->dv_fd);
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 2;
#endif #endif
return AVI_video_frames(lav_file->avi_fd); return AVI_video_frames(lav_file->avi_fd);
} }
@@ -468,12 +446,8 @@ int lav_video_width(lav_file_t *lav_file)
{ {
video_format = lav_file->format; internal_error = 0; /* for error messages */ video_format = lav_file->format; internal_error = 0; /* for error messages */
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format=='b') if(video_format=='b')
return rawdv_width(lav_file->dv_fd); return rawdv_width(lav_file->dv_fd);
#endif
#ifdef USE_GDK_PIXBUF
if(video_format=='x')
return (output_scale_width == 0 ? vj_picture_get_width( lav_file->picture ) : output_scale_width);
#endif #endif
return AVI_video_width(lav_file->avi_fd); return AVI_video_width(lav_file->avi_fd);
} }
@@ -482,12 +456,8 @@ int lav_video_height(lav_file_t *lav_file)
{ {
video_format = lav_file->format; internal_error = 0; /* for error messages */ video_format = lav_file->format; internal_error = 0; /* for error messages */
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_height( lav_file->dv_fd ); return rawdv_height( lav_file->dv_fd );
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return (output_scale_height == 0 ? vj_picture_get_height( lav_file->picture ) : output_scale_height);
#endif #endif
return AVI_video_height(lav_file->avi_fd); return AVI_video_height(lav_file->avi_fd);
} }
@@ -496,27 +466,20 @@ double lav_frame_rate(lav_file_t *lav_file)
{ {
video_format = lav_file->format; internal_error = 0; /* for error messages */ video_format = lav_file->format; internal_error = 0; /* for error messages */
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_fps(lav_file->dv_fd); return rawdv_fps(lav_file->dv_fd);
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return output_fps;
#endif #endif
return AVI_frame_rate(lav_file->avi_fd); return AVI_frame_rate(lav_file->avi_fd);
} }
int lav_video_interlacing(lav_file_t *lav_file) int lav_video_interlacing(lav_file_t *lav_file)
{ {
video_format = lav_file->format; internal_error = 0; /* for error messages */
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_interlacing(lav_file->dv_fd); return rawdv_interlacing(lav_file->dv_fd);
#endif #endif
#ifdef USE_GDK_PIXBUF return lav_file->interlacing;
if(video_format == 'x')
return LAV_NOT_INTERLACED;
#endif
return lav_file->interlacing;
} }
void lav_video_clipaspect(lav_file_t *lav_file, int *sar_w, int *sar_h) void lav_video_clipaspect(lav_file_t *lav_file, int *sar_w, int *sar_h)
@@ -553,13 +516,6 @@ const char *lav_video_compressor(lav_file_t *lav_file)
const char *tmp = (const char*) strdup("dvsd"); const char *tmp = (const char*) strdup("dvsd");
return tmp; return tmp;
} }
#endif
#ifdef USE_GDK_PIXBUF
if( video_format == 'x')
{
const char *tmp = (const char*) strdup("PICT");
return tmp;
}
#endif #endif
return AVI_video_compressor(lav_file->avi_fd); return AVI_video_compressor(lav_file->avi_fd);
} }
@@ -571,10 +527,6 @@ int lav_audio_channels(lav_file_t *lav_file)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_audio_channels(lav_file->dv_fd); return rawdv_audio_channels(lav_file->dv_fd);
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 0;
#endif #endif
return AVI_audio_channels(lav_file->avi_fd); return AVI_audio_channels(lav_file->avi_fd);
} }
@@ -586,10 +538,6 @@ int lav_audio_bits(lav_file_t *lav_file)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_audio_bits(lav_file->dv_fd); return rawdv_audio_bits(lav_file->dv_fd);
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x' )
return 0;
#endif #endif
return (AVI_audio_bits(lav_file->avi_fd)); return (AVI_audio_bits(lav_file->avi_fd));
} }
@@ -601,10 +549,6 @@ long lav_audio_rate(lav_file_t *lav_file)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format=='b') if(video_format=='b')
return rawdv_audio_rate(lav_file->dv_fd); return rawdv_audio_rate(lav_file->dv_fd);
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 0;
#endif #endif
return (AVI_audio_rate(lav_file->avi_fd)); return (AVI_audio_rate(lav_file->avi_fd));
} }
@@ -616,10 +560,6 @@ long lav_audio_clips(lav_file_t *lav_file)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format=='b') if(video_format=='b')
return rawdv_audio_bps(lav_file->dv_fd); return rawdv_audio_bps(lav_file->dv_fd);
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 0;
#endif #endif
return (AVI_audio_bytes(lav_file->avi_fd)/lav_file->bps); return (AVI_audio_bytes(lav_file->avi_fd)/lav_file->bps);
} }
@@ -630,10 +570,6 @@ long lav_frame_size(lav_file_t *lav_file, long frame)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_frame_size( lav_file->dv_fd ); return rawdv_frame_size( lav_file->dv_fd );
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 1;
#endif #endif
return (AVI_frame_size(lav_file->avi_fd,frame)); return (AVI_frame_size(lav_file->avi_fd,frame));
} }
@@ -644,10 +580,6 @@ int lav_seek_start(lav_file_t *lav_file)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_set_position( lav_file->dv_fd, 0 ); return rawdv_set_position( lav_file->dv_fd, 0 );
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 1;
#endif #endif
return (AVI_seek_start(lav_file->avi_fd)); return (AVI_seek_start(lav_file->avi_fd));
} }
@@ -658,10 +590,6 @@ int lav_set_video_position(lav_file_t *lav_file, long frame)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_set_position( lav_file->dv_fd, frame ); return rawdv_set_position( lav_file->dv_fd, frame );
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 1;
#endif #endif
return (AVI_set_video_position(lav_file->avi_fd,frame)); return (AVI_set_video_position(lav_file->avi_fd,frame));
} }
@@ -674,23 +602,10 @@ int lav_read_frame(lav_file_t *lav_file, uint8_t *vidbuf)
{ {
return rawdv_read_frame( lav_file->dv_fd, vidbuf ); return rawdv_read_frame( lav_file->dv_fd, vidbuf );
} }
#endif
#ifdef USE_GDK_PIXBUF
if(lav_file->format == 'x')
return -1;
#endif #endif
return (AVI_read_frame(lav_file->avi_fd,vidbuf)); return (AVI_read_frame(lav_file->avi_fd,vidbuf));
} }
#ifdef USE_GDK_PIXBUF
uint8_t *lav_get_frame_ptr( lav_file_t *lav_file )
{
if(lav_file->format == 'x')
return vj_picture_get( lav_file->picture );
return NULL;
}
#endif
int lav_is_DV(lav_file_t *lav_file) int lav_is_DV(lav_file_t *lav_file)
{ {
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
@@ -707,10 +622,6 @@ int lav_set_audio_position(lav_file_t *lav_file, long clip)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return 0; return 0;
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 0;
#endif #endif
return (AVI_set_audio_position(lav_file->avi_fd,clip*lav_file->bps)); return (AVI_set_audio_position(lav_file->avi_fd,clip*lav_file->bps));
} }
@@ -725,10 +636,6 @@ long lav_read_audio(lav_file_t *lav_file, uint8_t *audbuf, long samps)
#ifdef SUPPORT_READ_DV2 #ifdef SUPPORT_READ_DV2
if(video_format == 'b') if(video_format == 'b')
return rawdv_read_audio_frame( lav_file->dv_fd, audbuf ); return rawdv_read_audio_frame( lav_file->dv_fd, audbuf );
#endif
#ifdef USE_GDK_PIXBUF
if(video_format == 'x')
return 0;
#endif #endif
video_format = lav_file->format; internal_error = 0; /* for error messages */ video_format = lav_file->format; internal_error = 0; /* for error messages */
return (AVI_read_audio(lav_file->avi_fd,audbuf,samps*lav_file->bps)/lav_file->bps); return (AVI_read_audio(lav_file->avi_fd,audbuf,samps*lav_file->bps)/lav_file->bps);
@@ -794,6 +701,7 @@ lav_file_t *lav_open_input_file(char *filename, int mmap_size)
// if(!lav_fd->avi_fd) { if(lav_fd) free(lav_fd); return 0;} // if(!lav_fd->avi_fd) { if(lav_fd) free(lav_fd); return 0;}
if(lav_fd->avi_fd==NULL && AVI_errno == AVI_ERR_EMPTY ) if(lav_fd->avi_fd==NULL && AVI_errno == AVI_ERR_EMPTY )
{ {
veejay_msg(0, "Not an AVI file or AVI file is empty");
if(lav_fd) free(lav_fd); if(lav_fd) free(lav_fd);
return NULL; return NULL;
} }
@@ -805,49 +713,32 @@ lav_file_t *lav_open_input_file(char *filename, int mmap_size)
lav_fd->has_audio = (AVI_audio_bits(lav_fd->avi_fd)>0 && lav_fd->has_audio = (AVI_audio_bits(lav_fd->avi_fd)>0 &&
AVI_audio_format(lav_fd->avi_fd)==WAVE_FORMAT_PCM); AVI_audio_format(lav_fd->avi_fd)==WAVE_FORMAT_PCM);
video_comp = AVI_video_compressor(lav_fd->avi_fd); video_comp = AVI_video_compressor(lav_fd->avi_fd);
veejay_msg(0, "Found AVI file with %s fourcc", video_comp );
if(video_comp == NULL || strlen(video_comp) <= 0) if(video_comp == NULL || strlen(video_comp) <= 0)
{ if(lav_fd) free(lav_fd); return 0;} { if(lav_fd) free(lav_fd); return 0;}
} }
else if( AVI_errno==AVI_ERR_NO_AVI ) else if( AVI_errno==AVI_ERR_NO_AVI )
{ {
int ret = 0; int ret = 0;
#ifdef USE_GDK_PIXBUF #ifdef SUPPORT_READ_DV2
lav_fd->picture = vj_picture_open( (const char*) filename, lav_fd->dv_fd = rawdv_open_input_file(filename,mmap_size);
output_scale_width, output_scale_height, output_yuv ); if(lav_fd->dv_fd > 0)
if(lav_fd->picture) {
lav_fd->MJPG_chroma = rawdv_sampling( lav_fd->dv_fd );
if ( lav_fd->MJPG_chroma == -1 )
{ {
lav_fd->format = 'x'; veejay_msg(VEEJAY_MSG_ERROR, "Dont know how to treat this file");
lav_fd->has_audio = 0; ret = 0;
video_comp = strdup( "PICT" );
ret = 1;
} }
else else
{ {
#endif video_comp = rawdv_video_compressor( lav_fd->dv_fd );
lav_fd->format = 'b';
#ifdef SUPPORT_READ_DV2 lav_fd->has_audio = 0;
ret = 0; ret = 1;
lav_fd->dv_fd = rawdv_open_input_file(filename,mmap_size);
if(lav_fd->dv_fd > 0)
{
lav_fd->MJPG_chroma = rawdv_sampling( lav_fd->dv_fd );
if ( lav_fd->MJPG_chroma == -1 )
{
veejay_msg(VEEJAY_MSG_ERROR, "Dont know how to treat this file");
ret = 0;
}
else
{
video_comp = rawdv_video_compressor( lav_fd->dv_fd );
lav_fd->format = 'b';
lav_fd->has_audio = 0;
ret = 1;
}
}
#endif
#ifdef USE_GDK_PIXBUF
} }
#endif }
#endif
if(ret == 0 || video_comp == NULL) if(ret == 0 || video_comp == NULL)
{ {
free(lav_fd); free(lav_fd);
@@ -855,109 +746,91 @@ lav_file_t *lav_open_input_file(char *filename, int mmap_size)
veejay_msg(VEEJAY_MSG_ERROR, "Unable to load file '%s'", filename); veejay_msg(VEEJAY_MSG_ERROR, "Unable to load file '%s'", filename);
return 0; return 0;
} }
} }
lav_fd->bps = (lav_audio_channels(lav_fd)*lav_audio_bits(lav_fd)+7)/8; lav_fd->bps = (lav_audio_channels(lav_fd)*lav_audio_bits(lav_fd)+7)/8;
if(lav_fd->bps==0) lav_fd->bps=1; /* make it save since we will divide by that value */ if(lav_fd->bps==0) lav_fd->bps=1; /* make it save since we will divide by that value */
#ifdef USE_GDK_PIXBUF
if(strncasecmp(video_comp, "PICT",4) == 0 ) if(strncasecmp(video_comp, "div3",4)==0)
{ {
lav_fd->MJPG_chroma = (output_yuv == 1 ? CHROMA420: CHROMA422 ); lav_fd->MJPG_chroma = CHROMA420;
lav_fd->format = 'x'; lav_fd->format = 'D';
lav_fd->interlacing = LAV_NOT_INTERLACED;
veejay_msg(VEEJAY_MSG_WARNING, "Playing MS MPEG4v3 DivX Video. (Every frame should be an intra frame)" );
return lav_fd;
}
if(strncasecmp(video_comp,"mp4v",4)==0)
{
lav_fd->MJPG_chroma = CHROMA420;
lav_fd->format = 'M';
lav_fd->interlacing = LAV_NOT_INTERLACED;
veejay_msg(VEEJAY_MSG_WARNING, "Playing MPEG4 Video (Every frame should be an intra frame)");
return lav_fd;
}
/* Check compressor, no further action if not Motion JPEG/DV */
if (strncasecmp(video_comp,"iyuv",4)==0)
{
lav_fd->MJPG_chroma = CHROMA420;
lav_fd->format = 'Y';
lav_fd->interlacing = LAV_NOT_INTERLACED;
return lav_fd;
}
if (strncasecmp(video_comp,"yv16",4)==0)
{
lav_fd->MJPG_chroma = CHROMA422;
lav_fd->format = 'P';
lav_fd->interlacing = LAV_NOT_INTERLACED;
return lav_fd;
}
if( strncasecmp( video_comp, "i444",4 ) == 0 )
{
lav_fd->MJPG_chroma = CHROMA444;
lav_fd->format = 'Q';
lav_fd->interlacing = LAV_NOT_INTERLACED;
return lav_fd;
}
if (strncasecmp(video_comp,"dvsd",4)==0 || strncasecmp(video_comp,"dv",2)==0)
{
int gw = lav_video_height( lav_fd );
if( gw == 480 )
lav_fd->MJPG_chroma = CHROMA411;
else
lav_fd->MJPG_chroma = CHROMA422;
lav_fd->interlacing = LAV_INTER_BOTTOM_FIRST;
return lav_fd;
}
if( strncasecmp( video_comp, "hfyu", 4 ) == 0 )
{
lav_fd->MJPG_chroma = CHROMA422;
lav_fd->format = 'H';
lav_fd->interlacing = LAV_NOT_INTERLACED; lav_fd->interlacing = LAV_NOT_INTERLACED;
return lav_fd; return lav_fd;
} }
#endif
if(strncasecmp(video_comp, "div3",4)==0) {
lav_fd->MJPG_chroma = CHROMA420;
lav_fd->format = 'D';
lav_fd->interlacing = LAV_NOT_INTERLACED;
veejay_msg(VEEJAY_MSG_WARNING, "Playing MS MPEG4v3 DivX Video. (Every frame should be an intra frame)" );
return lav_fd;
}
if(strncasecmp(video_comp,"mp4v",4)==0) if (strncasecmp(video_comp, "mjpg", 4) == 0 || strncasecmp(video_comp,"mjpa",4)==0 ||
{ strncasecmp(video_comp, "jpeg", 4) == 0 || strncasecmp( video_comp ,"ljpg",4 ) == 0 )
lav_fd->MJPG_chroma = CHROMA420; {
lav_fd->format = 'M'; lav_fd->MJPG_chroma = CHROMA420;
lav_fd->interlacing = LAV_NOT_INTERLACED; lav_fd->format = 'a';
veejay_msg(VEEJAY_MSG_WARNING, "Playing MPEG4 Video (Every frame should be an intra frame)"); lav_fd->interlacing = LAV_INTER_UNKNOWN;
return lav_fd; lav_fd->is_MJPG = 1;
} ierr = 0;
frame = NULL;
if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT;
if ( (len = lav_frame_size(lav_fd,0)) <=0 ) goto ERREXIT;
if ( (frame = (unsigned char*) malloc(len)) == 0 ) { ierr=ERROR_MALLOC; goto ERREXIT; }
/* Check compressor, no further action if not Motion JPEG/DV */ if ( lav_read_frame(lav_fd,frame) <= 0 ) goto ERREXIT;
if (strncasecmp(video_comp,"iyuv",4)==0) if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT;
{ if( scan_jpeg(frame, len, 1) ) { ierr=ERROR_JPEG; goto ERREXIT; }
lav_fd->MJPG_chroma = CHROMA420;
lav_fd->format = 'Y';
lav_fd->interlacing = LAV_NOT_INTERLACED;
return lav_fd;
}
if (strncasecmp(video_comp,"yv16",4)==0)
{
lav_fd->MJPG_chroma = CHROMA422;
lav_fd->format = 'P';
lav_fd->interlacing = LAV_NOT_INTERLACED;
return lav_fd;
}
if (strncasecmp(video_comp,"dvsd",4)==0 || strncasecmp(video_comp,"dv",2)==0)
{
//veejay_msg(VEEJAY_MSG_DEBUG,"!! Guessing sampling type");
// lav_fd->MJPG_chroma = CHROMA422;
int gw = lav_video_height( lav_fd );
if( gw == 480 )
lav_fd->MJPG_chroma = CHROMA411;
else
lav_fd->MJPG_chroma = CHROMA422;
lav_fd->interlacing = LAV_INTER_BOTTOM_FIRST;
return lav_fd;
}
if (strncasecmp(video_comp, "mjpg", 4) == 0 || strncasecmp(video_comp,"mjpa",4)==0 ||
strncasecmp(video_comp, "jpeg", 4) == 0)
{
lav_fd->MJPG_chroma = CHROMA420;
lav_fd->format = 'a';
lav_fd->interlacing = LAV_INTER_UNKNOWN;
lav_fd->is_MJPG = 1;
// return lav_fd;
/* Make some checks on the video source, we read the first frame for that */
ierr = 0;
frame = NULL;
if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT;
if ( (len = lav_frame_size(lav_fd,0)) <=0 ) goto ERREXIT;
if ( (frame = (unsigned char*) malloc(len)) == 0 ) { ierr=ERROR_MALLOC; goto ERREXIT; }
if ( lav_read_frame(lav_fd,frame) <= 0 ) goto ERREXIT;
/* reset video position to 0 */
if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT;
if( scan_jpeg(frame, len, 1) ) { ierr=ERROR_JPEG; goto ERREXIT; }
/* We have to look to the JPEG SOF marker for further information
The SOF marker has the following format:
FF
C0
len_hi
len_lo
data_precision
height_hi
height_lo
width_hi
width_lo
num_components
And then 3 bytes for each component:
Component id
H, V sampling factors (as nibbles)
Quantization table number
*/
/* Check if the JPEG has the special 4:2:2 format needed for /* Check if the JPEG has the special 4:2:2 format needed for
some HW JPEG decompressors (the Iomega Buz, for example) */ some HW JPEG decompressors (the Iomega Buz, for example) */
@@ -1046,9 +919,9 @@ lav_file_t *lav_open_input_file(char *filename, int mmap_size)
if(frame) free(frame); if(frame) free(frame);
return lav_fd; return lav_fd;
} }
ierr = ERROR_FORMAT; ierr = ERROR_FORMAT;
ERREXIT: ERREXIT:
@@ -1098,21 +971,15 @@ const char *lav_strerror(void)
internal_error = 0; internal_error = 0;
return error_string; return error_string;
} }
if( video_format == 'b' )
{
sprintf(error_string, "rawdv strerror() not implemented");
internal_error = 0;
return error_string;
}
switch(video_format)
{ return AVI_strerror();
case 'a':
case 'A':
case 'Y':
case 'M':
case 'D':
return AVI_strerror();
default:
/* No or unknown video format */
if(errno) strerror(errno);
else sprintf(error_string,"No or unknown video format");
return error_string;
}
} }
@@ -1184,16 +1051,12 @@ int lav_fileno(lav_file_t *lav_file)
switch(lav_file->format) switch(lav_file->format)
{ {
case 'a': case 'b':
case 'A': res = -1;
case 'P': break;
case 'D':
case 'Y':
case 'M':
res = AVI_fileno( lav_file->avi_fd );
break;
default: default:
res = -1; res = AVI_fileno( lav_file->avi_fd );
break;
} }
return res; return res;

View File

@@ -39,7 +39,6 @@ static vj_dv_encoder *dv_encoder = NULL;
#endif #endif
//@@ FIXME //@@ FIXME
typedef struct typedef struct
{ {
AVCodec *codec; AVCodec *codec;
@@ -55,145 +54,228 @@ typedef struct
int encoder_id; int encoder_id;
int width; int width;
int height; int height;
int64_t time_unit;
} vj_encoder; } vj_encoder;
#define NUM_ENCODERS 8
static int out_pixel_format = FMT_420;
#ifdef STRICT_CHECKING #ifdef STRICT_CHECKING
#include <assert.h> #include <assert.h>
#endif #endif
#define YUV420_ONLY_CODEC(id) ( ( id == CODEC_ID_MJPEG || id == CODEC_ID_MJPEGB || id == CODEC_ID_MSMPEG4V3 || id == CODEC_ID_MPEG4 ) ? 1: 0) #define YUV420_ONLY_CODEC(id) ( ( id == CODEC_ID_MJPEG || id == CODEC_ID_MJPEGB || id == CODEC_ID_MSMPEG4V3 || id == CODEC_ID_MPEG4 ) ? 1: 0)
#define CODEC_ID_YUV420 998
#define CODEC_ID_YUV422 999
#define CODEC_ID_YUV444 1000
static char* el_get_codec_name(int codec_id ) static struct
{ {
char name[20]; int encoder_id;
switch(codec_id) int avcodec_id;
char *name;
} encoder_list_[] = {
{ ENCODER_MJPEG, CODEC_ID_MJPEG, "Motion JPEG" },
{ ENCODER_MJPEGB, CODEC_ID_MJPEGB, "MJPEGB" },
{ ENCODER_DVVIDEO, CODEC_ID_DVVIDEO, "Digital Video" },
{ ENCODER_DIVX, CODEC_ID_MSMPEG4V3 , "Divx 3;-)"},
{ ENCODER_YUV420, 998, "YUV 4:2:0 planar" },
{ ENCODER_YUV422, 999, "YUV 4:2:2 planar" },
{ ENCODER_YUV444, 1000, "YUV 4:4:4 planar" },
{ ENCODER_LOSSLESS, CODEC_ID_LJPEG, "Lossless JPEG" },
{ ENCODER_HUFFYUV, CODEC_ID_HUFFYUV, "Lossless HuffYUV" },
{ ENCODER_MPEG4, CODEC_ID_MPEG4, "MPEG4" },
{ -1,-1, NULL }
};
static int get_codec_id( int id )
{
int i;
for( i =0; encoder_list_[i].encoder_id != -1 ; i ++ )
{ {
case CODEC_ID_MJPEG: sprintf(name, "MJPEG"); break; if( encoder_list_[i].encoder_id == id )
case CODEC_ID_MPEG4: sprintf(name, "MPEG4"); break; return encoder_list_[i].avcodec_id;
case CODEC_ID_MSMPEG4V3: sprintf(name, "DIVX"); break;
case CODEC_ID_DVVIDEO: sprintf(name, "DVVideo"); break;
case -1 : sprintf(name, "RAW YUV"); break;
default:
sprintf(name, "Unknown"); break;
} }
char *res = strdup(name); return -1;
return res;
} }
static vj_encoder *_encoders[NUM_ENCODERS]; char* get_codec_name(int id )
static vj_encoder *vj_avcodec_new_encoder( int id, int w, int h, int pixel_format, float fps)
{ {
int i;
for( i =0; encoder_list_[i].encoder_id != -1 ; i ++ )
{
if( encoder_list_[i].encoder_id == id )
return encoder_list_[i].name;
}
return NULL;
}
void *vj_avcodec_new_encoder( int id, int w, int h, int pixel_format, double dfps)
{
int avcodec_id = get_codec_id( id );
char *descr = get_codec_name( id );
float fps = (float) dfps;
int sampling = 0;
if( avcodec_id == -1 )
{
veejay_msg(0, "Invalid codec '%d'", id );
return NULL;
}
vj_encoder *e = (vj_encoder*) vj_malloc(sizeof(vj_encoder)); vj_encoder *e = (vj_encoder*) vj_malloc(sizeof(vj_encoder));
if(!e) return NULL; if(!e) return NULL;
memset(e, 0, sizeof(vj_encoder)); memset(e, 0, sizeof(vj_encoder));
//@quality bad!!
if(id != 998 && id != 999 ) if( id != ENCODER_YUV420 && id != ENCODER_YUV422 && id != ENCODER_YUV444)
{ {
#ifdef __FALLBACK_LIBDV e->codec = avcodec_find_encoder( avcodec_id );
if(id != CODEC_ID_DVVIDEO)
if(!e->codec )
{ {
#endif free(e);
e->codec = avcodec_find_encoder( id ); veejay_msg(0, "Cannot open codec '%s'",
if(!e->codec) descr );
{ return NULL;
char *descr = el_get_codec_name(id);
veejay_msg(VEEJAY_MSG_ERROR, "Cannot find Encoder codec %s", descr );
free(descr);
}
#ifdef __FALLBACK_LIBDV
} }
#endif
}
if( id != 998 && id != 999 )
{
#ifdef __FALLBACK_LIBDV
if(id != CODEC_ID_DVVIDEO )
{
#endif
e->context = avcodec_alloc_context(); e->context = avcodec_alloc_context();
e->context->bit_rate = 2750 * 1024;
// e->context->bit_rate = 5750 * 1024;
e->context->max_b_frames =0; e->context->max_b_frames =0;
//e->context->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
e->context->width = w; e->context->width = w;
e->context->height = h; e->context->height = h;
e->context->time_base.den = 1; e->context->time_base.den = 1;
e->context->time_base.num = fps; // = (AVRational) { 1, fps }; e->context->time_base.num = fps; // = (AVRational) { 1, fps };
e->context->qcompress = 0.0; e->context->qcompress = 0.0;
e->context->qblur = 0.0; e->context->qblur = 0.0;
e->context->flags = CODEC_FLAG_QSCALE; e->context->flags = CODEC_FLAG_QSCALE;
e->context->gop_size = 0; e->context->gop_size = 0;
e->context->b_frame_strategy = 0;
e->context->sub_id = 0; e->context->sub_id = 0;
e->context->me_method = 0; // motion estimation algorithm e->context->me_method = 0; // motion estimation algorithm
e->context->workaround_bugs = FF_BUG_AUTODETECT; e->context->workaround_bugs = FF_BUG_AUTODETECT;
e->context->prediction_method = 0; e->context->prediction_method = 0;
e->context->dct_algo = FF_DCT_AUTO; //global_quality? e->context->dct_algo = FF_DCT_AUTO; //global_quality?
e->context->global_quality = 1;
e->context->strict_std_compliance = FF_COMPLIANCE_INOFFICIAL;
e->time_unit = 1000000 / e->context->time_base.num;
switch( avcodec_id )
{
case CODEC_ID_MJPEG:
case CODEC_ID_MJPEGB:
case CODEC_ID_LJPEG:
e->context->pix_fmt = PIX_FMT_YUVJ420P;
if( pixel_format != FMT_420 )
sampling = 1;
break;
case CODEC_ID_MPEG4:
case CODEC_ID_MSMPEG4V3:
e->context->pix_fmt = PIX_FMT_YUV420P;
if( pixel_format != FMT_420 )
sampling = 1;
break;
case CODEC_ID_HUFFYUV:
if(pixel_format == FMT_422 ) {
e->context->pix_fmt = PIX_FMT_YUV422P;
} else if ( pixel_format == FMT_420 ) {
e->context->pix_fmt = PIX_FMT_YUV420P;
} else if ( pixel_format == FMT_444 ) {
e->context->pix_fmt = PIX_FMT_YUV422P;
sampling = 1;
}
break;
}
if ( avcodec_open( e->context, e->codec ) < 0 )
{
free(e->context);
free( e );
return NULL;
}
}
switch( avcodec_id )
{
case CODEC_ID_YUV420:
case CODEC_ID_YUV422:
if( pixel_format == FMT_444 )
sampling = 1;
break;
case CODEC_ID_YUV444:
if( pixel_format != FMT_444 )
{
veejay_msg(0, "Please run veejay -P2 for YUV 4:4:4 planar support");
free(e);
return NULL;
}
break;
}
//@ ffmpeg MJPEG accepts only 4:2:0 if(sampling)
{
e->sampler = subsample_init_copy( w,h );
switch(pixel_format)
{
case FMT_444:
e->sampling_mode = SSM_422_444;
e->uv_width = w;
break;
case FMT_422:
e->sampling_mode = SSM_420_422;
e->uv_width = w;
break;
default:
e->uv_width =w /2;
break;
}
}
if( avcodec_id == CODEC_ID_YUV420 )
{
switch( pixel_format )
{
case FMT_422:
e->sampling_mode = SSM_420_422;
break;
case FMT_444:
e->sampling_mode = SSM_420_JPEG_BOX;
break;
}
} else if (avcodec_id == CODEC_ID_YUV422 )
{
switch( pixel_format ) switch( pixel_format )
{ {
case FMT_420: case FMT_420:
e->uv_len = (w * h ) / 4; e->sampling_mode = SSM_420_422;
e->uv_width = w / 2;
e->context->pix_fmt = PIX_FMT_YUVJ420P;
break;
case FMT_422:
e->uv_len = (w * h ) / 2;
e->uv_width = w / 2;
e->context->pix_fmt = PIX_FMT_YUVJ422P;
break; break;
case FMT_444: case FMT_444:
e->uv_len = (w * h ); e->sampling_mode = SSM_420_422;
e->uv_width = w;
e->context->pix_fmt = PIX_FMT_YUVJ444P;
break; break;
} }
if( id == CODEC_ID_MJPEG || id == CODEC_ID_MPEG4 || id == CODEC_ID_MSMPEG4V3)
{
if(pixel_format != FMT_420)
{
e->sampler = subsample_init( w );
e->sampling_mode = (pixel_format == FMT_422 ? SSM_420_422 :
SSM_422_444 );
e->uv_len = (w * h ) / 4;
e->uv_width = (w / 2);
if( id == CODEC_ID_MJPEG )
e->context->pix_fmt = PIX_FMT_YUVJ420P;
else
e->context->pix_fmt = PIX_FMT_YUV420P;
}
}
if ( avcodec_open( e->context, e->codec ) < 0 )
{
if(e) free(e);
return NULL;
}
#ifdef __FALLBACK_LIBDV
}
#endif
} }
e->len = ( w * h ); e->len = ( w * h );
switch( pixel_format )
{
case FMT_444:
e->uv_len = e->len; break;
case FMT_422:
e->uv_len = e->len/2; break;
case FMT_420:
e->uv_len = e->len/4;break;
}
e->width = w; e->width = w;
e->height = h; e->height = h;
e->out_fmt = pixel_format; e->out_fmt = pixel_format;
e->encoder_id = id; e->encoder_id = avcodec_id;
return e; return (void*) e;
} }
static void vj_avcodec_close_encoder( vj_encoder *av ) void vj_avcodec_close_encoder( vj_encoder *av )
{ {
if(av) if(av)
{ {
@@ -201,76 +283,14 @@ static void vj_avcodec_close_encoder( vj_encoder *av )
{ {
avcodec_close( av->context ); avcodec_close( av->context );
free(av->context); free(av->context);
if(av->sampler)
subsample_free(av->sampler);
} }
free(av); free(av);
} }
av = NULL; av = NULL;
} }
int vj_avcodec_init(int w, int h , double dfps, int fmt, int norm)
{
float fps = (float) dfps;
_encoders[ENCODER_MJPEG] = vj_avcodec_new_encoder( CODEC_ID_MJPEG, w,h, fmt,fps );
if(!_encoders[ENCODER_MJPEG])
{
veejay_msg(0 ,"Unable to initialize MJPEG codec");
return 0;
}
#ifdef __FALLBACK_LIBDV
dv_encoder = vj_dv_init_encoder( w,h,norm, out_pixel_format);
if(!dv_encoder)
{
veejay_msg(VEEJAY_MSG_ERROR, "Unable to initialize quasar DV codec");
return 0;
}
#else
_encoders[ENCODER_DVVIDEO] = vj_avcodec_new_encoder( CODEC_ID_DVVIDEO, w,h, fmt,fps );
if(!_encoders[ENCODER_DVVIDEO])
{
veejay_msg(0, "Unable to initialize DV codec");
return 0;
}
#endif
_encoders[ENCODER_DIVX] = vj_avcodec_new_encoder( CODEC_ID_MSMPEG4V3 , w,h, fmt,fps);
if(!_encoders[ENCODER_DIVX])
{
veejay_msg(0, "Unable to initialize DIVX (msmpeg4v3) codec");
return 0;
}
_encoders[ENCODER_MPEG4] = vj_avcodec_new_encoder( CODEC_ID_MPEG4, w,h, fmt,fps);
if(!_encoders[ENCODER_MPEG4])
{
veejay_msg(0, "Unable to initialize MPEG4 codec");
return 0;
}
_encoders[ENCODER_YUV420] = vj_avcodec_new_encoder( 999, w,h,fmt,fps);
if(!_encoders[ENCODER_YUV420])
{
veejay_msg(0, "Unable to initialize YUV 4:2:0 planer (RAW)");
return 0;
}
_encoders[ENCODER_YUV422] = vj_avcodec_new_encoder( 998, w,h,fmt,fps);
if(!_encoders[ENCODER_YUV422])
{
veejay_msg(0, "Unable to initialize YUV 4:2:2 planar (RAW)");
return 0;
}
return 1;
}
int vj_avcodec_free()
{
int i;
for( i = 0; i < NUM_ENCODERS; i++)
{
if(_encoders[i]) vj_avcodec_close_encoder(_encoders[i]);
}
#ifdef __FALLBACK_LIBDV
vj_dv_free_encoder(dv_encoder);
#endif
return 1;
}
void yuv422p_to_yuv420p3( uint8_t *src, uint8_t *dst[3], int w, int h) void yuv422p_to_yuv420p3( uint8_t *src, uint8_t *dst[3], int w, int h)
{ {
AVPicture pict1,pict2; AVPicture pict1,pict2;
@@ -391,79 +411,129 @@ int yuv420p_to_yuv422p( uint8_t *sY,uint8_t *sCb, uint8_t *sCr, uint8_t *dst[3],
static int vj_avcodec_copy_frame( vj_encoder *av, uint8_t *src[3], uint8_t *dst ) static int vj_avcodec_copy_frame( vj_encoder *av, uint8_t *src[3], uint8_t *dst )
{ {
uint8_t *yuv[3];
if(!av) if(!av)
{ {
veejay_msg(VEEJAY_MSG_ERROR, "No encoder !!"); veejay_msg(VEEJAY_MSG_ERROR, "No encoder !!");
return 0; return 0;
} }
if( (av->encoder_id == 999 && av->out_fmt == PIX_FMT_YUV420P) || (av->encoder_id == 998 && av->out_fmt == PIX_FMT_YUV422P))
{
/* copy */
veejay_memcpy( dst, src[0], av->len );
veejay_memcpy( dst+(av->len), src[1], av->uv_len );
veejay_memcpy( dst+(av->len+av->uv_len) , src[2], av->uv_len);
return ( av->len + av->uv_len + av->uv_len );
}
/* copy by converting */
if( av->encoder_id == 999 && av->out_fmt == PIX_FMT_YUV422P)
{
yuv422p_to_yuv420p( src, dst, av->width, av->height);
return ( av->len + (av->len/4) + (av->len/4));
}
if( av->encoder_id == 998 && av->out_fmt == PIX_FMT_YUV420P)
if (av->encoder_id == CODEC_ID_YUV420 )
{ {
uint8_t *d[3]; switch( av->out_fmt )
d[0] = dst; {
d[1] = dst + av->len; case FMT_420:
d[2] = dst + av->len + (av->len / 2); veejay_memcpy( dst, src[0], av->len );
yuv420p_to_yuv422p2( src[0],src[1],src[2], d, av->width,av->height ); veejay_memcpy( dst + av->len, src[1], av->uv_len );
return ( av->len + av->len ); veejay_memcpy( dst + av->len + av->uv_len, src[2], av->uv_len );
return (av->len + av->uv_len + av->uv_len);
break;
case FMT_422:
case FMT_444:
chroma_subsample_copy( av->sampling_mode,
av->sampler,
src,
av->width,
av->height,
yuv );
veejay_memcpy( dst, yuv[0], av->len );
veejay_memcpy( dst+av->len, yuv[1], av->len/4 );
veejay_memcpy( dst+av->len+(av->len/4),yuv[2], av->len/4);
return (av->len + (av->len/4) + (av->len/4) );
break;
}
}
else if ( av->encoder_id == CODEC_ID_YUV422 )
{
switch(av->out_fmt)
{
case FMT_422:
veejay_memcpy( dst, src[0], av->len );
veejay_memcpy( dst + av->len, src[1], av->uv_len );
veejay_memcpy( dst + av->len + av->uv_len, src[2], av->uv_len );
return (av->len + av->uv_len + av->uv_len);
case FMT_444:
case FMT_420:
chroma_subsample_copy( av->sampling_mode,
av->sampler,
src,
av->width,
av->height,
yuv );
veejay_memcpy( dst, yuv[0], av->len );
veejay_memcpy( dst+av->len, yuv[1], av->len/2 );
veejay_memcpy( dst+av->len+(av->len/2),yuv[2], av->len/2);
return (av->len + (av->len/2) + (av->len/2) );
}
} else if( av->encoder_id == CODEC_ID_YUV444 ){
switch(av->out_fmt)
{
case FMT_444:
veejay_memcpy( dst, src[0], av->len );
veejay_memcpy( dst + av->len, src[1], av->uv_len );
veejay_memcpy( dst + av->len + av->len, src[2], av->uv_len );
return (av->len + av->uv_len + av->uv_len);
default:
#ifdef STRICT_CHECKING
assert(0);
#endif
break;
}
} }
return 0; return 0;
} }
int vj_avcodec_encode_frame( int format, uint8_t **src, uint8_t *buf, int buf_len)
int vj_avcodec_encode_frame( void *codec, int format, void *dsrc, uint8_t *buf, int buf_len, uint64_t nframe)
{ {
AVFrame pict; AVFrame p;
vj_encoder *av = _encoders[format]; VJFrame *src = (VJFrame*) dsrc;
uint8_t *yuv[3];
vj_encoder *av = (vj_encoder*) codec;
#ifdef STRICT_CHECKING #ifdef STRICT_CHECKING
if( av == NULL )
veejay_msg(0 ,"Invalid format: %d",format );
assert( av != NULL ); assert( av != NULL );
#endif #endif
int res=0; int res=0;
memset( &pict, 0, sizeof(pict));
if(format == ENCODER_YUV420) // no compression, just copy
return vj_avcodec_copy_frame( _encoders[ENCODER_YUV420],src, buf );
if(format == ENCODER_YUV422) // no compression, just copy
return vj_avcodec_copy_frame( _encoders[ENCODER_YUV422],src, buf );
#ifdef __FALLBACK_LIBDV
if(format == ENCODER_DVVIDEO )
return vj_dv_encode_frame( dv_encoder,src, buf );
#endif
pict.quality = 1;
pict.data[0] = src[0];
pict.data[1] = src[1];
pict.data[2] = src[2];
pict.linesize[0] = av->context->width;
pict.linesize[1] = av->uv_width;
pict.linesize[2] = av->uv_width;
if( av->encoder_id == CODEC_ID_YUV420 || av->encoder_id == CODEC_ID_YUV422 || av->encoder_id == CODEC_ID_YUV444 )
{
return vj_avcodec_copy_frame( av, src->data, buf );
}
memset( &p, 0, sizeof(AVFrame));
if(av->sampler) if(av->sampler)
{ {
chroma_subsample( av->sampling_mode, chroma_subsample_copy( av->sampling_mode,
av->sampler, av->sampler,
src, src,
av->width, av->width,
av->height ); av->height,
yuv );
} }
res = avcodec_encode_video( av->context, buf, buf_len, &pict ); p.data[0] = yuv[0];
p.data[1] = yuv[1];
p.data[2] = yuv[2];
p.linesize[0] = av->width;
p.linesize[1] = av->uv_width;
p.linesize[2] = av->uv_width;
p.pts = av->time_unit * nframe;
p.quality = 1;
res = avcodec_encode_video( av->context, buf, buf_len, &p );
return res; return res;
} }

View File

@@ -19,11 +19,10 @@
#ifndef VJ_AVCODEC_H #ifndef VJ_AVCODEC_H
#define VJ_AVCODEC_H #define VJ_AVCODEC_H
int vj_avcodec_init(int w, int h , double fps, int fmt, int norm);
int vj_avcodec_encode_frame( int format, uint8_t *src[3], uint8_t *dst, int dst_len); void *vj_avcodec_new_encoder( int id, int w, int h, int pixel_format, double dfps);
int vj_avcodec_free(); int vj_avcodec_encode_frame( void *codec, int format, void *dsrc, uint8_t *buf, int buf_len, uint64_t nframe);
/* color space conversion routines, should go somewhere else someday /* color space conversion routines, should go somewhere else someday
together with subsample.c/colorspace.c into some lib together with subsample.c/colorspace.c into some lib

View File

@@ -569,13 +569,6 @@ int vj_el_scan_video_frame(void *edl)
} }
uint8_t *data = vj_malloc( sizeof(uint8_t*) * el->video_width * el->video_height * 4 ); uint8_t *data = vj_malloc( sizeof(uint8_t*) * el->video_width * el->video_height * 4 );
if(lav_filetype( el->lav_fd[N_EL_FILE(n)] ) == 'x')
{
veejay_msg(VEEJAY_MSG_ERROR, "What is this?");
return 0;
}
res = lav_read_frame(el->lav_fd[N_EL_FILE(n)], data); res = lav_read_frame(el->lav_fd[N_EL_FILE(n)], data);
if( res <= 0 ) if( res <= 0 )

View File

@@ -73,6 +73,7 @@ typedef struct
uint8_t *buf; uint8_t *buf;
uint8_t *YUV_to_YCbCr[2]; uint8_t *YUV_to_YCbCr[2];
int jyuv; int jyuv;
uint8_t *planes[4];
} yuv_sampler_t; } yuv_sampler_t;
static uint8_t *sample_buffer = NULL; static uint8_t *sample_buffer = NULL;
@@ -94,6 +95,29 @@ void *subsample_init(int len)
return (void*) s; return (void*) s;
} }
void *subsample_init_copy(int w, int h)
{
void *ret = NULL;
int len = w;
yuv_sampler_t *s = (yuv_sampler_t*) vj_malloc(sizeof(yuv_sampler_t) );
if(!s)
return ret;
memset( s, 0 , sizeof( yuv_sampler_t ));
s->buf = (uint8_t*) vj_malloc(sizeof(uint8_t) * len );
s->YUV_to_YCbCr[0] = NULL;
s->YUV_to_YCbCr[1] = NULL;
if(!s->buf)
return ret;
s->planes[0] = (uint8_t*) vj_malloc( sizeof(uint8_t) * w * h );
s->planes[1] = (uint8_t*) vj_malloc( sizeof(uint8_t) * w * h );
s->planes[2] = (uint8_t*) vj_malloc( sizeof(uint8_t) * w * h );
return (void*) s;
}
void subsample_free(void *data) void subsample_free(void *data)
{ {
yuv_sampler_t *sampler = (yuv_sampler_t*) data; yuv_sampler_t *sampler = (yuv_sampler_t*) data;
@@ -105,6 +129,12 @@ void subsample_free(void *data)
if(sampler->YUV_to_YCbCr[1]) if(sampler->YUV_to_YCbCr[1])
free(sampler->YUV_to_YCbCr[1]); free(sampler->YUV_to_YCbCr[1]);
free(sampler); free(sampler);
if(sampler->planes[0])
free(sampler->planes[0]);
if(sampler->planes[1])
free(sampler->planes[1]);
if(sampler->planes[2])
free(sampler->planes[2]);
} }
sampler = NULL; sampler = NULL;
} }
@@ -936,6 +966,46 @@ static void ss_444_to_420mpeg2(uint8_t *buffer, int width, int height)
void chroma_subsample_copy(subsample_mode_t mode, void *data, VJFrame *frame,
int width, int height, uint8_t *res[])
{
yuv_sampler_t *sampler = (yuv_sampler_t*) data;
veejay_memcpy( sampler->planes[1], frame->data[1], frame->uv_len );
veejay_memcpy( sampler->planes[2], frame->data[2], frame->uv_len );
switch (mode) {
case SSM_420_JPEG_BOX:
case SSM_420_JPEG_TR:
ss_444_to_420jpeg(sampler->planes[1], width, height);
ss_444_to_420jpeg(sampler->planes[2], width, height);
#ifdef HAVE_ASM_MMX
emms();
#endif
break;
case SSM_420_MPEG2:
ss_444_to_420mpeg2(sampler->planes[1], width, height);
ss_444_to_420mpeg2(sampler->planes[2], width, height);
break;
case SSM_422_444:
ss_444_to_422(data,sampler->planes[1],width,height);
ss_444_to_422(data,sampler->planes[2],width,height);
#ifdef HAVE_ASM_MMX
emms();
#endif
break;
case SSM_420_422:
ss_422_to_420(sampler->planes[1],width,height);
ss_422_to_420(sampler->planes[2],width,height);
break;
default:
break;
}
res[0] = frame->data[0];
res[1] = sampler->planes[1];
res[2] = sampler->planes[2];
}
void chroma_subsample(subsample_mode_t mode, void *data, uint8_t *ycbcr[], void chroma_subsample(subsample_mode_t mode, void *data, uint8_t *ycbcr[],
int width, int height) int width, int height)

View File

@@ -74,8 +74,13 @@ typedef struct AFrame_t
#define ENCODER_MJPEG 0 #define ENCODER_MJPEG 0
#define ENCODER_YUV420 1 #define ENCODER_YUV420 1
#define ENCODER_YUV422 2 #define ENCODER_YUV422 2
#define ENCODER_MPEG4 3 #define ENCODER_YUV444 3
#define ENCODER_DIVX 4 #define ENCODER_MPEG4 4
#define ENCODER_DVVIDEO 5 #define ENCODER_DIVX 5
#define ENCODER_DVVIDEO 6
#define ENCODER_LOSSLESS 7
#define ENCODER_HUFFYUV 8
#define ENCODER_MJPEGB 9
#define NUM_ENCODERS 10
#endif #endif

View File

@@ -247,15 +247,9 @@ int veejay_init_project_from_args( veejay_t *info, int w, int h, float fps, int
svit->bits = 16; svit->bits = 16;
svit->bps = bps; svit->bps = bps;
avcodec_init();
avcodec_register_all(); avcodec_register_all();
int n = vj_avcodec_init( w,h,(double)fps,fmt,norm);
#ifdef STRICT_CHECKING
assert( n == 1 );
#endif
veejay_msg(2, "Project settings:"); veejay_msg(2, "Project settings:");
veejay_msg(2, "\tvideo settings: %d x %d, @%2.2f in %s", svit->w,svit->h,svit->fps, (svit->norm ? "NTSC" :"PAL") ); veejay_msg(2, "\tvideo settings: %d x %d, @%2.2f in %s", svit->w,svit->h,svit->fps, (svit->norm ? "NTSC" :"PAL") );
veejay_msg(2, "\taudio settings: %ld Hz, %d bits, %d channels, %d bps", veejay_msg(2, "\taudio settings: %ld Hz, %d bits, %d channels, %d bps",
@@ -694,7 +688,6 @@ int veejay_close(veejay_t * info)
void veejay_deinit(veejay_t *info) void veejay_deinit(veejay_t *info)
{ {
vj_avcodec_free();
vj_server_shutdown(info->status_socket); vj_server_shutdown(info->status_socket);
vj_server_shutdown(info->command_socket); vj_server_shutdown(info->command_socket);
vj_server_shutdown(info->frame_socket); vj_server_shutdown(info->frame_socket);

View File

@@ -342,7 +342,14 @@ int main(int argc, char **argv)
veejay_free(info); veejay_free(info);
return 0; return 0;
} }
if( dump_ )
{
vj_init_vevo_events();
vj_event_vevo_dump();
return 0;
}
info->sync_correction = synchronization_; info->sync_correction = synchronization_;
info->sync_skip_frames = skip_; info->sync_skip_frames = skip_;
@@ -388,7 +395,6 @@ int main(int argc, char **argv)
smp_check(); smp_check();
char *mem_func = get_memcpy_descr(); char *mem_func = get_memcpy_descr();
if(mem_func) if(mem_func)
{ {
@@ -396,21 +402,13 @@ int main(int argc, char **argv)
free(mem_func); free(mem_func);
} }
if(veejay_init( info ) < 0 ) if(veejay_init( info ) < 0 )
{ {
veejay_msg(VEEJAY_MSG_ERROR, "Initializing veejay"); veejay_msg(VEEJAY_MSG_ERROR, "Initializing veejay");
return 0; return 0;
} }
if( dump_ )
{
vj_event_vevo_dump();
veejay_quit(info);
veejay_free(info);
return 0;
}
if(!veejay_main(info)) if(!veejay_main(info))
{ {
veejay_msg(VEEJAY_MSG_ERROR, "Cannot start main playback cycle"); veejay_msg(VEEJAY_MSG_ERROR, "Cannot start main playback cycle");

View File

@@ -1796,8 +1796,6 @@ void vj_event_sample_configure_recorder( void *ptr, const char format[], va_list
v->video_info ); v->video_info );
if( error ) if( error )
veejay_msg(0, "Unable to configure the recorder"); veejay_msg(0, "Unable to configure the recorder");
else
veejay_msg(0, "Recorder ready");
} }
} }

View File

@@ -718,7 +718,7 @@ void vj_init_vevo_events(void)
"Configure sample recorder", "Configure sample recorder",
vj_event_sample_configure_recorder, vj_event_sample_configure_recorder,
4, 4,
VIMS_REQUIRE_ALL_PARAMS, VIMS_LONG_PARAMS|VIMS_REQUIRE_ALL_PARAMS,
SAMPLE_ID_HELP, SAMPLE_ID_HELP,
0, 0,
"Dataformat", "Dataformat",

View File

@@ -108,11 +108,13 @@ typedef struct
int rec; int rec;
int con; int con;
int max_size; int max_size;
char format; int format;
char aformat;
void *fd; void *fd;
long tf; long tf;
long nf; long nf;
uint8_t *buf; uint8_t *buf;
void *codec;
} samplerecord_t; } samplerecord_t;
//! \typedef sample_runtime_data Sample Runtime Data structure //! \typedef sample_runtime_data Sample Runtime Data structure
@@ -2543,23 +2545,38 @@ int sample_configure_recorder( void *sample, int format, const char *filename, i
{ {
char fmt = 'Y'; //default uncompressed format char fmt = 'Y'; //default uncompressed format
int max_size = 0; int max_size = 0;
char *codec;
sample_runtime_data *srd = (sample_runtime_data*) sample; sample_runtime_data *srd = (sample_runtime_data*) sample;
sampleinfo_t *sit = srd->info; sampleinfo_t *sit = srd->info;
samplerecord_t *rec = srd->record; samplerecord_t *rec = srd->record;
if( !filename )
{
veejay_msg(VEEJAY_MSG_ERROR, "No filename given");
return -1;
}
if( nframes <= 0 )
{
veejay_msg(VEEJAY_MSG_ERROR, "No frames to record");
return -1;
}
if( sit->rec ) if( sit->rec )
{ {
veejay_msg(VEEJAY_MSG_ERROR, "Please stop the recorder first"); veejay_msg(VEEJAY_MSG_ERROR, "Please stop the recorder first");
return 1; return 1;
} }
switch( format ) switch( format )
{ {
//@ todo: not all encoders here, mod lav_io.c
case ENCODER_DVVIDEO: case ENCODER_DVVIDEO:
fmt = 'd'; fmt = 'd';
if( ps->w == 720 && (ps->h == 480 || ps->h == 576 ) ) if( ps->w == 720 && (ps->h == 480 || ps->h == 576 ) )
max_size = ( ps->h == 480 ? 120000: 144000 ); max_size = ( ps->h == 480 ? 120000: 144000 );
break; break;
case ENCODER_MJPEG: case ENCODER_MJPEG:
fmt = 'a'; fmt = 'a';
@@ -2567,11 +2584,15 @@ int sample_configure_recorder( void *sample, int format, const char *filename, i
break; break;
case ENCODER_YUV420: case ENCODER_YUV420:
fmt = 'Y'; fmt = 'Y';
max_size = 2 * ps->h * ps->w; max_size = ( ps->h * ps->w ) + (ps->h * ps->w / 2 );
break; break;
case ENCODER_YUV422: case ENCODER_YUV422:
fmt = 'P'; fmt = 'P';
max_size = 3 * ps->h * ps->w; max_size = 2 * (ps->h * ps->w);
break;
case ENCODER_YUV444:
fmt = 'Q';
max_size = 3 * (ps->h * ps->w);
break; break;
case ENCODER_MPEG4: case ENCODER_MPEG4:
fmt = 'M'; fmt = 'M';
@@ -2579,38 +2600,57 @@ int sample_configure_recorder( void *sample, int format, const char *filename, i
break; break;
case ENCODER_DIVX: case ENCODER_DIVX:
fmt = 'D'; fmt = 'D';
max_size = 65545 * 4; max_size = 65535 * 4;
break;
case ENCODER_LOSSLESS:
fmt = 'L';
max_size = 65535 * 4;
break;
case ENCODER_MJPEGB:
fmt = 'A';
max_size = 65535 * 4;
break;
case ENCODER_HUFFYUV:
fmt = 'H';
max_size = 65535 * 4;
break; break;
break;
default: default:
veejay_msg(VEEJAY_MSG_ERROR, "Unknown recording format"); veejay_msg(VEEJAY_MSG_ERROR, "Unknown recording format");
return 1; return 1;
break; break;
} }
codec = get_codec_name( format );
rec->format = format;
rec->aformat = fmt;
if(nframes > 0) if(nframes > 0)
rec->tf = nframes; //sample_tc_to_frames( timecode, ps->fps); rec->tf = nframes; //sample_tc_to_frames( timecode, ps->fps);
else else
rec->tf = (long) (ps->fps * 60); rec->tf = (long) (ps->fps * 60);
rec->format = fmt;
int error = vevo_property_set( srd->info_port, "filename", VEVO_ATOM_TYPE_STRING,1, &filename ); int error = vevo_property_set( srd->info_port, "filename", VEVO_ATOM_TYPE_STRING,1, &filename );
#ifdef STRICT_CHECKING #ifdef STRICT_CHECKING
assert( error == VEVO_NO_ERROR ); assert( error == VEVO_NO_ERROR );
#endif #endif
rec->buf = (uint8_t*) vj_malloc(sizeof(uint8_t) * max_size ); rec->buf = (uint8_t*) vj_malloc(sizeof(uint8_t) * max_size );
if(!rec->buf)
if(!rec->buf )
{ {
veejay_msg(VEEJAY_MSG_ERROR, "Insufficient memory to allocate buffer for recorder"); veejay_msg(VEEJAY_MSG_ERROR, "Insufficient memory to allocate buffer for recorder");
return 1; return 1;
} }
memset( rec->buf,0, max_size ); memset( rec->buf,0, max_size );
rec->con = 1; rec->con = 1;
rec->max_size = max_size; rec->max_size = max_size;
veejay_msg(VEEJAY_MSG_INFO, "Record to %s (%d frames) in %s", filename, rec->tf, codec );
return VEVO_NO_ERROR; return VEVO_NO_ERROR;
} }
@@ -2635,9 +2675,21 @@ int sample_start_recorder( void *sample , sample_video_info_t *ps)
assert( destination != NULL ); assert( destination != NULL );
assert( rec->tf > 0 ); assert( rec->tf > 0 );
#endif #endif
rec->codec = vj_avcodec_new_encoder(
rec->format, ps->w,ps->h,ps->fmt, (double)ps->fps );
if(!rec->codec)
{
veejay_msg(VEEJAY_MSG_ERROR, "Unable to initialize '%s' codec",
get_codec_name( rec->format ) );
free(rec->buf);
memset( rec, 0 , sizeof( samplerecord_t ));
return -1;
}
rec->fd = (void*) rec->fd = (void*)
lav_open_output_file( destination, rec->format, lav_open_output_file( destination, rec->aformat,
ps->w, ps->h, ps->inter, ps->fps, ps->w, ps->h, ps->inter, ps->fps,
ps->bps, ps->chans, ps->rate ); ps->bps, ps->chans, ps->rate );
@@ -2672,6 +2724,7 @@ int sample_stop_recorder( void *sample )
if(!rec->rec) if(!rec->rec)
return 1; return 1;
vj_avcodec_close_encoder( rec->codec );
lav_close( (lav_file_t*) rec->fd ); lav_close( (lav_file_t*) rec->fd );
if( rec->buf ) if( rec->buf )
@@ -2681,7 +2734,7 @@ int sample_stop_recorder( void *sample )
rec->max_size = 0; rec->max_size = 0;
sit->rec = 0.0; sit->rec = 0.0;
return VEVO_NO_ERROR; return VEVO_NO_ERROR;
} }
@@ -2692,21 +2745,24 @@ int sample_record_frame( void *sample, VJFrame *frame, uint8_t *audio_buffer, in
samplerecord_t *rec = srd->record; samplerecord_t *rec = srd->record;
sampleinfo_t *sit = srd->info; sampleinfo_t *sit = srd->info;
int compr_len = vj_avcodec_encode_frame( int compr_len = vj_avcodec_encode_frame(
rec->nf++, rec->codec,
rec->format, rec->format,
frame->data, (void*)frame,
rec->buf, rec->buf,
rec->max_size ); rec->max_size,
(uint64_t) rec->nf );
if( compr_len <= 0 ) if( compr_len <= 0 )
{ {
veejay_msg(0, "Cannot encode frame %d", rec->nf );
return sample_stop_recorder( sample ); return sample_stop_recorder( sample );
} }
int n = lav_write_audio( (lav_file_t*) rec->fd, rec->buf, compr_len ); int n = lav_write_frame( (lav_file_t*) rec->fd, rec->buf, compr_len,1 );
if( n <= 0 ) if( n < 0 )
{ {
veejay_msg(VEEJAY_MSG_ERROR, "Writing video frame"); veejay_msg(VEEJAY_MSG_ERROR, "Writing video frame");
return sample_stop_recorder(sample); return sample_stop_recorder(sample);
@@ -2722,6 +2778,8 @@ int sample_record_frame( void *sample, VJFrame *frame, uint8_t *audio_buffer, in
} }
} }
rec->nf ++;
if( rec->nf >= rec->tf ) if( rec->nf >= rec->tf )
{ {
veejay_msg(VEEJAY_MSG_INFO, "Done recording"); veejay_msg(VEEJAY_MSG_INFO, "Done recording");