|
|
#endif | #endif |
| |
#ifdef HAVE_LIBQUICKTIME | #ifdef HAVE_LIBQUICKTIME |
#include <quicktime.h> |
#include <quicktime/quicktime.h> |
|
#include <quicktime/lqt.h> |
#endif | #endif |
| |
extern int AVI_errno; | extern int AVI_errno; |
|
|
int asize, int achans, long arate) | int asize, int achans, long arate) |
{ | { |
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)); |
|
char *extension, *tempfile; |
| |
if(lav_fd==0) { internal_error=ERROR_MALLOC; return 0; } | if(lav_fd==0) { internal_error=ERROR_MALLOC; return 0; } |
| |
|
|
lav_fd->qt_fd = 0; | lav_fd->qt_fd = 0; |
lav_fd->format = format; | lav_fd->format = format; |
/* Sanity check: do not create a quicktime file that is named with .avi */ | /* Sanity check: do not create a quicktime file that is named with .avi */ |
if(rindex(filename, '.') != NULL) |
extension = rindex(filename, '.'); |
|
if (extension != NULL) |
{ | { |
if((format == 'a' || format == 'A') && strcmp(rindex(filename, '.')+1, "avi")) { |
extension++; |
internal_error = ERROR_FORMAT; |
switch(format) |
return 0; |
{ |
} |
case 'a': |
if(format == 'q' && (strcmp(rindex(filename, '.')+1, "qt") |
case 'A': |
&& strcmp(rindex(filename, '.')+1, "mov") && strcmp(rindex(filename, '.')+1,"moov"))) { |
if (strcmp(extension, "avi") && strcmp(extension, "AVI")) |
internal_error = ERROR_FORMAT; |
{ |
return 0; |
internal_error = ERROR_FORMAT; |
} |
return 0; |
if(format == 'j' && strcmp(rindex(filename, '.')+1, "jpg") |
} |
&& strcmp(rindex(filename, '.')+1, "jpeg")) { |
break; |
internal_error = ERROR_FORMAT; |
case 'q': |
return 0; |
if (strcmp(extension, "qt") && strcmp(extension, "QT") && |
} |
strcmp(extension, "mov") && strcmp(extension, "MOV") && |
|
strcmp(extension,"moov") && strcmp(extension,"MOOV")) |
|
{ |
|
internal_error = ERROR_FORMAT; |
|
return 0; |
|
} |
|
break; |
|
case 'j': |
|
if (strcmp(extension, "jpg") && strcmp(extension, "jpg") && |
|
strcmp(extension,"jpeg") && strcmp(extension,"JPEG")) |
|
{ |
|
internal_error = ERROR_FORMAT; |
|
return 0; |
|
} |
|
break; |
|
} |
} | } |
lav_fd->interlacing = interlaced ? lav_query_polarity(format) : | lav_fd->interlacing = interlaced ? lav_query_polarity(format) : |
LAV_NOT_INTERLACED; | LAV_NOT_INTERLACED; |
lav_fd->has_audio = (asize>0 && achans>0); | lav_fd->has_audio = (asize>0 && achans>0); |
lav_fd->bps = (asize*achans+7)/8; | lav_fd->bps = (asize*achans+7)/8; |
lav_fd->is_MJPG = 1; |
|
lav_fd->MJPG_chroma = CHROMAUNKNOWN; | lav_fd->MJPG_chroma = CHROMAUNKNOWN; |
| |
switch(format) | switch(format) |
|
|
if (asize) AVI_set_audio(lav_fd->avi_fd, achans, arate, asize, WAVE_FORMAT_PCM); | if (asize) AVI_set_audio(lav_fd->avi_fd, achans, arate, asize, WAVE_FORMAT_PCM); |
return lav_fd; | return lav_fd; |
| |
case 'j': { |
case 'j': |
|
|
/* Open JPEG output file */ | /* Open JPEG output file */ |
char tempfile[256]; |
tempfile = (char *)malloc(strlen(filename) + strlen(TMP_EXTENSION) + 1); |
|
if (tempfile == NULL) |
|
{ |
|
internal_error=ERROR_MALLOC; |
|
return(0); |
|
} |
strcpy(tempfile, filename); | strcpy(tempfile, filename); |
strcat(tempfile, TMP_EXTENSION); | strcat(tempfile, TMP_EXTENSION); |
|
|
lav_fd->jpeg_filename = strdup(filename); | lav_fd->jpeg_filename = strdup(filename); |
lav_fd->jpeg_fd = open(tempfile, O_CREAT | O_TRUNC | O_WRONLY, 0644); | lav_fd->jpeg_fd = open(tempfile, O_CREAT | O_TRUNC | O_WRONLY, 0644); |
|
free(tempfile); |
return lav_fd; | return lav_fd; |
} |
|
case 'q': |
|
| |
|
case 'q': |
#ifdef HAVE_LIBQUICKTIME | #ifdef HAVE_LIBQUICKTIME |
/* open quicktime output file */ | /* open quicktime output file */ |
| |
|
|
} | } |
| |
int lav_close(lav_file_t *lav_file) | int lav_close(lav_file_t *lav_file) |
{ |
{ |
int res; | int res; |
|
char *tempfile; |
| |
video_format = lav_file->format; internal_error = 0; /* for error messages */ | video_format = lav_file->format; internal_error = 0; /* for error messages */ |
| |
switch(lav_file->format) |
switch (lav_file->format) |
{ |
{ |
case 'a': | case 'a': |
case 'A': | case 'A': |
res = AVI_close( lav_file->avi_fd ); | res = AVI_close( lav_file->avi_fd ); |
break; | break; |
case 'j': { |
case 'j': |
char tempfile[256]; |
tempfile = (char *)malloc(strlen(lav_file->jpeg_filename) + |
|
strlen(TMP_EXTENSION) + 1); |
|
if (tempfile == NULL) |
|
{ |
|
res = -1; |
|
break; |
|
} |
strcpy(tempfile, lav_file->jpeg_filename); | strcpy(tempfile, lav_file->jpeg_filename); |
strcat(tempfile, TMP_EXTENSION); | strcat(tempfile, TMP_EXTENSION); |
res = close(lav_file->jpeg_fd); | res = close(lav_file->jpeg_fd); |
rename(tempfile, lav_file->jpeg_filename); | rename(tempfile, lav_file->jpeg_filename); |
|
free(tempfile); |
free(lav_file->jpeg_filename); | free(lav_file->jpeg_filename); |
break; | break; |
} |
|
#ifdef HAVE_LIBQUICKTIME | #ifdef HAVE_LIBQUICKTIME |
case 'q': | case 'q': |
res = quicktime_close( lav_file->qt_fd ); | res = quicktime_close( lav_file->qt_fd ); |
|
|
#endif | #endif |
default: | default: |
res = -1; | res = -1; |
} |
} |
|
|
free(lav_file); | free(lav_file); |
|
|
return res; | return res; |
} |
} |
| |
int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count) | int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count) |
{ | { |
|
|
| |
int lav_write_audio(lav_file_t *lav_file, uint8_t *buff, long samps) | int lav_write_audio(lav_file_t *lav_file, uint8_t *buff, long samps) |
{ | { |
int res; |
int res = -1; |
#ifdef HAVE_LIBQUICKTIME |
#ifdef HAVE_LIBQUICKTIME |
int n, nb; |
int i, j; |
uint8_t *hbuff; |
int16_t *buff16 = (int16_t *)buff, **qt_audion; |
|
int channels = lav_audio_channels(lav_file); |
|
int bits = lav_audio_bits(lav_file); |
#endif | #endif |
| |
video_format = lav_file->format; internal_error = 0; /* for error messages */ | video_format = lav_file->format; internal_error = 0; /* for error messages */ |
|
|
{ | { |
case 'a': | case 'a': |
case 'A': | case 'A': |
res = AVI_write_audio( lav_file->avi_fd, buff, samps*lav_file->bps); |
res = AVI_write_audio(lav_file->avi_fd, buff, samps * lav_file->bps); |
break; | break; |
#ifdef HAVE_LIBQUICKTIME | #ifdef HAVE_LIBQUICKTIME |
case 'q': | case 'q': |
if(lav_audio_bits(lav_file)==16) |
if (bits != 16 || channels > 1) |
{ |
{ |
nb = samps*2*lav_audio_channels(lav_file); |
/* Deinterleave the audio into the two channels and/or convert |
hbuff = (uint8_t *) malloc(nb); |
* bits per sample to the required format. |
if(!hbuff) { internal_error=ERROR_MALLOC; return -1; } |
*/ |
for(n=0;n<nb;n+=2) |
qt_audion = malloc(channels * sizeof(*qt_audion)); |
{ hbuff[n] = buff[n+1]; hbuff[n+1] = buff[n]; } |
for (i = 0; i < channels; i++) |
res = quicktime_write_audio( lav_file->qt_fd, (char*)hbuff, samps, 0 ); |
qt_audion[i] = malloc(samps * sizeof(**qt_audion)); |
free(hbuff); |
|
} |
if (bits == 16) |
else |
for (i = 0; i < samps; i++) |
res = quicktime_write_audio( lav_file->qt_fd, (char*)buff, samps, 0 ); |
for (j = 0; j < channels; j++) |
break; |
qt_audion[j][i] = buff16[channels * i + j]; |
|
else |
|
if (bits == 8) |
|
for (i = 0; i < samps; i++) |
|
for (j = 0; j < channels; j++) |
|
qt_audion[j][i] = ((int16_t)(buff[channels * i + j]) << 8) ^ 0x8000; |
|
|
|
if (bits == 8 || bits == 16) |
|
res = lqt_encode_audio_track(lav_file->qt_fd, qt_audion, NULL, samps, 0); |
|
|
|
for (i = 0; i < channels; i++) |
|
free(qt_audion[i]); |
|
free(qt_audion); |
|
} else { |
|
qt_audion = &buff16; |
|
res = lqt_encode_audio_track(lav_file->qt_fd, qt_audion, NULL, samps, 0); |
|
} |
|
break; |
#endif | #endif |
default: | default: |
res = -1; |
break; |
} | } |
| |
return res; | return res; |
} | } |
| |
|
|
|
|
long lav_video_frames(lav_file_t *lav_file) | long lav_video_frames(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 */ |
|
|
return; | return; |
} | } |
| |
int lav_video_is_MJPG(lav_file_t *lav_file) |
|
{ |
|
return lav_file->is_MJPG; |
|
} |
|
|
|
int lav_video_MJPG_chroma(lav_file_t *lav_file) | int lav_video_MJPG_chroma(lav_file_t *lav_file) |
{ | { |
return lav_file->MJPG_chroma; | return lav_file->MJPG_chroma; |
} | } |
| |
|
|
const char *lav_video_compressor(lav_file_t *lav_file) | const char *lav_video_compressor(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 */ |
|
|
return -1; | return -1; |
} | } |
| |
|
|
int lav_set_audio_position(lav_file_t *lav_file, long sample) | int lav_set_audio_position(lav_file_t *lav_file, long sample) |
{ | { |
if(!lav_file->has_audio) return 0; | if(!lav_file->has_audio) return 0; |
|
|
return AVI_set_audio_position(lav_file->avi_fd,sample*lav_file->bps); | return AVI_set_audio_position(lav_file->avi_fd,sample*lav_file->bps); |
#ifdef HAVE_LIBQUICKTIME | #ifdef HAVE_LIBQUICKTIME |
case 'q': | case 'q': |
return quicktime_set_audio_position(lav_file->qt_fd,sample,0); |
quicktime_set_audio_position(lav_file->qt_fd,sample,0); |
#endif | #endif |
} | } |
return -1; | return -1; |
|
|
long lav_read_audio(lav_file_t *lav_file, uint8_t *audbuf, long samps) | long lav_read_audio(lav_file_t *lav_file, uint8_t *audbuf, long samps) |
{ | { |
#ifdef HAVE_LIBQUICKTIME | #ifdef HAVE_LIBQUICKTIME |
long res, n, t; |
int64_t last_pos, start_pos; |
|
int res, i, j; |
|
int16_t *audbuf16 = (int16_t *)audbuf, **qt_audion; |
|
int channels = lav_audio_channels(lav_file); |
|
int bits = lav_audio_bits(lav_file); |
#endif | #endif |
| |
if(!lav_file->has_audio) | if(!lav_file->has_audio) |
{ | { |
internal_error = ERROR_NOAUDIO; | internal_error = ERROR_NOAUDIO; |
return -1; |
return(-1); |
} | } |
video_format = lav_file->format; internal_error = 0; /* for error messages */ | video_format = lav_file->format; internal_error = 0; /* for error messages */ |
switch(lav_file->format) | switch(lav_file->format) |
|
|
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; |
#ifdef HAVE_LIBQUICKTIME | #ifdef HAVE_LIBQUICKTIME |
case 'q': | case 'q': |
res = quicktime_read_audio(lav_file->qt_fd,(char*)audbuf,samps,0)/lav_file->bps; |
if (bits != 16 || channels > 1) |
if(res<=0) return res; |
{ |
if(lav_audio_bits(lav_file)==16) |
qt_audion = malloc(channels * sizeof(*qt_audion)); |
{ |
for (i = 0; i < channels; i++) |
for(n=0;n<res*2*lav_audio_channels(lav_file);n+=2) |
qt_audion[i] = malloc(samps * sizeof(**qt_audion)); |
{ |
} else { |
t = audbuf[n]; |
qt_audion = &audbuf16; |
audbuf[n] = audbuf[n+1]; |
} |
audbuf[n+1] = t; |
|
} |
start_pos = quicktime_audio_position(lav_file->qt_fd, 0); |
} |
lqt_decode_audio_track(lav_file->qt_fd, qt_audion, NULL, samps, 0); |
return res; |
last_pos = lqt_last_audio_position(lav_file->qt_fd, 0); |
|
res = last_pos - start_pos; |
|
|
|
if (res > 0 && (bits != 16 || channels > 1)) |
|
{ |
|
/* Interleave the channels of audio into the one buffer provided |
|
* and/or convert bits per sample to the required format. |
|
*/ |
|
if (bits == 16) |
|
for (i = 0; i < res; i++) |
|
for (j = 0; j < channels; j++) |
|
audbuf16[channels * i + j] = qt_audion[j][i]; |
|
else |
|
if (bits == 8) |
|
for (i = 0; i < res; i++) |
|
for (j = 0; j < channels; j++) |
|
audbuf[channels * i + j] = (qt_audion[j][i] >> 8) + 0x80; |
|
} |
|
|
|
if (bits != 16 || channels > 1) |
|
{ |
|
for (i = 0; i < channels; i++) |
|
free(qt_audion[i]); |
|
free(qt_audion); |
|
} |
|
return res; |
#endif | #endif |
} | } |
return -1; | return -1; |
} | } |
| |
int lav_filetype(lav_file_t *lav_file) |
|
{ |
|
return lav_file->format; |
|
} |
|
|
|
lav_file_t *lav_open_input_file(char *filename) | lav_file_t *lav_open_input_file(char *filename) |
{ | { |
int n; | int n; |
|
|
lav_fd->qt_fd = 0; | lav_fd->qt_fd = 0; |
lav_fd->format = 0; | lav_fd->format = 0; |
lav_fd->interlacing = LAV_INTER_UNKNOWN; | lav_fd->interlacing = LAV_INTER_UNKNOWN; |
lav_fd->sar_w = 0; /* (0,0) == unknown */ |
lav_fd->sar_w = 1; /* unknown - assume square pixels */ |
lav_fd->sar_h = 0; |
lav_fd->sar_h = 1; |
lav_fd->has_audio = 0; | lav_fd->has_audio = 0; |
lav_fd->bps = 0; | lav_fd->bps = 0; |
lav_fd->is_MJPG = 0; |
|
lav_fd->MJPG_chroma = CHROMAUNKNOWN; | lav_fd->MJPG_chroma = CHROMAUNKNOWN; |
| |
/* open video file, try AVI first */ | /* open video file, try AVI first */ |
|
|
return lav_fd; | return lav_fd; |
} | } |
| |
lav_fd->is_MJPG = 1; |
|
|
|
/* Make some checks on the video source, we read the first frame for that */ | /* Make some checks on the video source, we read the first frame for that */ |
| |
ierr = 0; | ierr = 0; |
|
|
} | } |
} | } |
| |
|
|
|
|
#ifdef HAVE_LIBDV | #ifdef HAVE_LIBDV |
static int check_DV2_input(lav_file_t *lav_fd) | static int check_DV2_input(lav_file_t *lav_fd) |
{ | { |
|
|
double len = 0; | double len = 0; |
unsigned char *frame = NULL; | unsigned char *frame = NULL; |
| |
lav_fd->is_MJPG = 0; |
|
|
|
/* Make some checks on the video source, we read the first frame for that */ | /* Make some checks on the video source, we read the first frame for that */ |
| |
if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT; | if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT; |
|
|
} | } |
#endif | #endif |
| |
|
|
|
|
static int check_YUV420_input(lav_file_t *lav_fd) | static int check_YUV420_input(lav_file_t *lav_fd) |
{ | { |
int ierr = 0; | int ierr = 0; |
double len = 0; | double len = 0; |
unsigned char *frame = NULL; | unsigned char *frame = NULL; |
| |
lav_fd->is_MJPG = 0; |
|
|
|
/* Make some checks on the video source, we read the first frame for that */ | /* Make some checks on the video source, we read the first frame for that */ |
| |
if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT; | if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT; |
|
|
| |
return res; | return res; |
} | } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|