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.
908 lines
20 KiB
908 lines
20 KiB
/*
|
|
* fileinfo.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.
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef HAVE_LIBDV
|
|
#include <libdv/dv.h>
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "libtc/libtc.h"
|
|
#include "libtc/xio.h"
|
|
#include "ioaux.h"
|
|
#include "tc.h"
|
|
|
|
/* forward declaration */
|
|
static int scan_header_dv(const char *buf);
|
|
|
|
unsigned char asfhdrguid[16]={0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C};
|
|
|
|
unsigned char mxfmagic[]={0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01};
|
|
|
|
unsigned char zero_pad[4]={0,0,0,0};
|
|
|
|
static int cmp_32_bits(char *buf, long x)
|
|
{
|
|
|
|
if(0) {
|
|
tc_log_msg(__FILE__, "MAGIC: 0x%02lx 0x%02lx 0x%02lx 0x%02lx %s", (x >> 24) & 0xff, ((x >> 16) & 0xff), ((x >> 8) & 0xff), ((x ) & 0xff), filetype(x));
|
|
tc_log_msg(__FILE__, " FILE: 0x%02x 0x%02x 0x%02x 0x%02x", buf[0] & 0xff, buf[1] & 0xff, buf[2] & 0xff, buf[3] & 0xff);
|
|
}
|
|
|
|
if ((uint8_t)buf[0] != ((x >> 24) & 0xff))
|
|
return 0;
|
|
if ((uint8_t)buf[1] != ((x >> 16) & 0xff))
|
|
return 0;
|
|
if ((uint8_t)buf[2] != ((x >> 8) & 0xff))
|
|
return 0;
|
|
if ((uint8_t)buf[3] != ((x ) & 0xff))
|
|
return 0;
|
|
|
|
// OK found it
|
|
return 1;
|
|
}
|
|
|
|
static int cmp_28_bits(char *buf, long x)
|
|
{
|
|
|
|
if(0) {
|
|
tc_log_msg(__FILE__, "MAGIC: 0x%02lx 0x%02lx 0x%02lx 0x%02lx %s", (x >> 24) & 0xff, ((x >> 16) & 0xff), ((x >> 8) & 0xff), ((x ) & 0xff), filetype(x));
|
|
tc_log_msg(__FILE__, " FILE: 0x%02x 0x%02x 0x%02x 0x%02x", buf[0] & 0xff, buf[1] & 0xff, buf[2] & 0xff, buf[3] & 0xff);
|
|
}
|
|
|
|
if ((uint8_t)buf[0] != ((x >> 24) & 0xff))
|
|
return 0;
|
|
if ((uint8_t)buf[1] != ((x >> 16) & 0xff))
|
|
return 0;
|
|
if ((uint8_t)buf[2] != ((x >> 8) & 0xff))
|
|
return 0;
|
|
if ((uint8_t)(buf[3] & 0xf0) != ((x ) & 0xff))
|
|
return 0;
|
|
|
|
// OK found it
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int cmp_16_bits(char *buf, long x)
|
|
{
|
|
|
|
int16_t sync_word=0;
|
|
|
|
if(0) {
|
|
tc_log_msg(__FILE__, "MAGIC: 0x%02lx 0x%02lx 0x%02lx 0x%02lx %s", (x >> 24) & 0xff, ((x >> 16) & 0xff), ((x >> 8) & 0xff), ((x ) & 0xff), filetype(x));
|
|
tc_log_msg(__FILE__, " FILE: 0x%02x 0x%02x 0x%02x 0x%02x", buf[0] & 0xff, buf[1] & 0xff, buf[2] & 0xff, buf[3] & 0xff);
|
|
}
|
|
|
|
sync_word = (sync_word << 8) + (uint8_t) buf[0];
|
|
sync_word = (sync_word << 8) + (uint8_t) buf[1];
|
|
|
|
if(sync_word == (int16_t) x) return 1;
|
|
|
|
// not found;
|
|
return 0;
|
|
}
|
|
|
|
static int save_read(char *buf, int bytes, off_t offset, int fdes)
|
|
{
|
|
|
|
// returns 0 if ok, 1 on failure to read first bytes
|
|
|
|
// rewind
|
|
if(xio_lseek(fdes, offset, SEEK_SET)<0) {
|
|
tc_log_warn(__FILE__, "[%s:%d] file seek error: %s",
|
|
__FILE__, __LINE__, strerror(errno));
|
|
return(1);
|
|
}
|
|
|
|
if(xio_read(fdes, buf, bytes)<bytes) {
|
|
tc_log_warn(__FILE__, "[%s:%d] file read error: %s",
|
|
__FILE__, __LINE__, strerror(errno));
|
|
return(1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
#define MAX_PROBE_BYTES 4096
|
|
|
|
long fileinfo(int fdes, int skip)
|
|
{
|
|
|
|
char buf[MAX_PROBE_BYTES];
|
|
|
|
off_t off=0;
|
|
|
|
int cc=0;
|
|
|
|
long id=TC_MAGIC_UNKNOWN, offset;
|
|
|
|
// assume this is a valid file descriptor
|
|
|
|
// are we at offset defined by skip?
|
|
if((offset = xio_lseek(fdes, skip, SEEK_CUR)) < 0) {
|
|
if(errno==ESPIPE) return(TC_MAGIC_PIPE);
|
|
return(TC_MAGIC_ERROR);
|
|
}
|
|
|
|
// refuse to work with a file not at offset 0
|
|
if(offset != skip) {
|
|
tc_log_error(__FILE__, "file pointer not at requested offset %d - exit", skip);
|
|
return(TC_MAGIC_ERROR);
|
|
}
|
|
|
|
off +=skip;
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* zero padding detection
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
if(save_read(buf, 4, off, fdes)) goto exit;
|
|
|
|
while(memcmp(buf, zero_pad, 4)==0) {
|
|
off +=4; //preserves byte order
|
|
if(off> TC_MAX_SEEK_BYTES) goto exit;
|
|
if(save_read(buf, 4, off, fdes)) goto exit;
|
|
}
|
|
|
|
if(off<0) goto exit;
|
|
|
|
//tc_log_msg(__FILE__, "off=%d '%c' '%c' '%c' '%c'", off, buf[0], buf[1], buf[2], buf[3]);
|
|
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 2 byte section, read 4 bytes
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
if(save_read(buf, 4, off, fdes)) goto exit;
|
|
|
|
// AC3
|
|
|
|
if(cmp_16_bits(buf, TC_MAGIC_AC3)) {
|
|
id = TC_MAGIC_AC3;
|
|
goto exit;
|
|
}
|
|
|
|
// MP3 audio
|
|
|
|
if(cmp_16_bits(buf, TC_MAGIC_MP3)) {
|
|
id = TC_MAGIC_MP3;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf, TC_MAGIC_MP3_2_5)) {
|
|
id = TC_MAGIC_MP3_2_5;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf, TC_MAGIC_MP3_2)) {
|
|
id = TC_MAGIC_MP3_2;
|
|
goto exit;
|
|
}
|
|
|
|
// MP2 audio
|
|
|
|
if(cmp_16_bits(buf, TC_MAGIC_MP2) || cmp_16_bits(buf, TC_MAGIC_MP2_FC)) {
|
|
id = TC_MAGIC_MP2;
|
|
goto exit;
|
|
}
|
|
|
|
if ( ((((buf[0]<<8)&0xff00)|buf[1])&0xfff8) == 0xfff0) {
|
|
if ( (buf[1]&0x02) == 0x02) {
|
|
id = TC_MAGIC_MP3;
|
|
goto exit;
|
|
}
|
|
if ( (buf[1]&0x01) == 0x01) {
|
|
id = TC_MAGIC_MP2;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// TIFF image
|
|
|
|
if (cmp_16_bits(buf, TC_MAGIC_TIFF1)) {
|
|
id = TC_MAGIC_TIFF1;
|
|
goto exit;
|
|
}
|
|
if (cmp_16_bits(buf, TC_MAGIC_TIFF2)) {
|
|
id = TC_MAGIC_TIFF2;
|
|
goto exit;
|
|
}
|
|
|
|
// BMP image
|
|
|
|
if (cmp_16_bits(buf, TC_MAGIC_BMP)) {
|
|
id = TC_MAGIC_BMP;
|
|
goto exit;
|
|
}
|
|
|
|
// SGI image
|
|
|
|
if (cmp_16_bits(buf, TC_MAGIC_SGI)) {
|
|
id = TC_MAGIC_SGI;
|
|
goto exit;
|
|
}
|
|
|
|
// PPM image
|
|
|
|
if (strncmp (buf, "P6", 2)==0) {
|
|
id = TC_MAGIC_PPM;
|
|
goto exit;
|
|
}
|
|
|
|
// PGM image
|
|
|
|
if (strncmp (buf, "P5", 2)==0) {
|
|
id = TC_MAGIC_PGM;
|
|
goto exit;
|
|
}
|
|
|
|
// SGI image
|
|
|
|
if (cmp_16_bits(buf, TC_MAGIC_SGI)) {
|
|
id = TC_MAGIC_SGI;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
// transport stream
|
|
|
|
if (buf[0] == (uint8_t) TC_MAGIC_TS) {
|
|
id = TC_MAGIC_TS;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 4 byte section
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
if(save_read(buf, 4, off, fdes)) goto exit;
|
|
|
|
|
|
// DTS
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_DTS)) {
|
|
id = TC_MAGIC_DTS;
|
|
goto exit;
|
|
}
|
|
|
|
// VOB
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_VOB)) {
|
|
id = TC_MAGIC_VOB;
|
|
goto exit;
|
|
}
|
|
|
|
// MPEG Video / .VDR
|
|
|
|
if(cmp_28_bits(buf, TC_MAGIC_MPEG)) {
|
|
id = TC_MAGIC_MPEG; /* FIXME: it's PES? */
|
|
goto exit;
|
|
}
|
|
|
|
// DV
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_DV_NTSC)) {
|
|
id = TC_MAGIC_DV_NTSC;
|
|
goto exit;
|
|
}
|
|
|
|
// DV
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_DV_PAL)) {
|
|
id = TC_MAGIC_DV_PAL;
|
|
goto exit;
|
|
}
|
|
|
|
// OGG stream
|
|
|
|
if (strncmp (buf, "OggS", 4)==0) {
|
|
id = TC_MAGIC_OGG;
|
|
goto exit;
|
|
}
|
|
|
|
// M2V
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_M2V)) {
|
|
id = TC_MAGIC_MPEG_ES;
|
|
goto exit;
|
|
}
|
|
|
|
// NUV
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_NUV)) {
|
|
id = TC_MAGIC_NUV;
|
|
goto exit;
|
|
}
|
|
|
|
// OGG
|
|
|
|
if (strncasecmp(buf, "OggS", 4) == 0) {
|
|
id = TC_MAGIC_OGG;
|
|
goto exit;
|
|
}
|
|
|
|
// Real Media
|
|
if(strncasecmp(buf,".RMF", 4)==0) {
|
|
id = TC_MAGIC_RMF;
|
|
goto exit;
|
|
}
|
|
|
|
// PV3
|
|
if (memcmp(buf, "PV3\1", 4) == 0 || memcmp(buf, "PV3\2", 4) == 0) {
|
|
id = TC_MAGIC_PV3;
|
|
goto exit;
|
|
}
|
|
|
|
// PVN
|
|
if (buf[0]=='P' && buf[1]=='V'
|
|
&& (buf[2]>='4' && buf[2]<='6')
|
|
&& (buf[3]=='a' || buf[3]=='b' || buf[3]=='d' || buf[3]=='f')
|
|
) {
|
|
id = TC_MAGIC_PVN;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
// MP3 audio + odd 0 padding
|
|
|
|
if(cmp_16_bits(buf+1, TC_MAGIC_MP3)) {
|
|
id = TC_MAGIC_MP3;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+1, TC_MAGIC_MP3_2_5)) {
|
|
id = TC_MAGIC_MP3_2_5;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+1, TC_MAGIC_MP3_2)) {
|
|
id = TC_MAGIC_MP3_2;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+2, TC_MAGIC_MP3)) {
|
|
id = TC_MAGIC_MP3;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+2, TC_MAGIC_MP3_2_5)) {
|
|
id = TC_MAGIC_MP3_2_5;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+2, TC_MAGIC_MP3_2)) {
|
|
id = TC_MAGIC_MP3_2;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_ID3)) {
|
|
id = TC_MAGIC_ID3;
|
|
goto exit;
|
|
}
|
|
|
|
// iTunes sets an ID3 header that way at the beginning. We search for an
|
|
// syncword first so it should just work.
|
|
if (buf[0] == 'I' && buf[1] == 'D' && buf[2] == '3' && buf[3] == 0x02) {
|
|
id = TC_MAGIC_MP3;
|
|
goto exit;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 8 byte section
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
if(save_read(buf, 8, off, fdes)) goto exit;
|
|
|
|
// YUV4MPEG
|
|
|
|
if (strncmp (buf, "YUV4MPEG", 8)==0) {
|
|
id = TC_MAGIC_YUV4MPEG;
|
|
goto exit;
|
|
}
|
|
|
|
// BSDAV
|
|
|
|
if (strncmp (buf, "BSDAV", 5)==0) {
|
|
id = TC_MAGIC_BSDAV;
|
|
goto exit;
|
|
}
|
|
|
|
// MOV
|
|
|
|
if(strncasecmp(buf+4,"moov", 4) ==0 ||
|
|
strncasecmp(buf+4,"cmov", 4) ==0 ||
|
|
strncasecmp(buf+4,"mdat", 4) ==0 ||
|
|
strncasecmp(buf+4,"ftyp", 4) ==0 ||
|
|
strncasecmp(buf+4,"pnot", 4) ==0) {
|
|
id = TC_MAGIC_MOV;
|
|
goto exit;
|
|
}
|
|
|
|
// PNG
|
|
|
|
if (cmp_32_bits(buf, TC_MAGIC_PNG) &&
|
|
cmp_32_bits(buf+4, 0x0D0A1A0A)) {
|
|
id = TC_MAGIC_PNG;
|
|
goto exit;
|
|
}
|
|
|
|
// GIF
|
|
|
|
if (strncasecmp(buf, "GIF87a", 6) == 0 ||
|
|
strncasecmp(buf, "GIF89a", 6) == 0) {
|
|
id = TC_MAGIC_GIF;
|
|
goto exit;
|
|
}
|
|
|
|
// XML
|
|
|
|
if(strncasecmp(buf,"<?xml", 5) ==0) {
|
|
id = TC_MAGIC_XML;
|
|
goto exit;
|
|
}
|
|
|
|
// vncrec log file
|
|
|
|
if(strncasecmp(buf,"vncLog",6) ==0 ) {
|
|
id = TC_MAGIC_VNC;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 12 byte section
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
|
|
if(save_read(buf, 12, off, fdes)) goto exit;
|
|
|
|
// YUV4MPEG2
|
|
|
|
if (strncmp (buf, "YUV4MPEG2", 9)==0) {
|
|
id = TC_MAGIC_YUV4MPEG;
|
|
goto exit;
|
|
}
|
|
|
|
// AVI
|
|
if(strncasecmp(buf ,"RIFF",4) ==0 &&
|
|
strncasecmp(buf+8,"AVI ",4) ==0 ) {
|
|
id = TC_MAGIC_AVI;
|
|
goto exit;
|
|
}
|
|
|
|
// JPEG
|
|
if (cmp_32_bits(buf, TC_MAGIC_JPEG) &&
|
|
strncasecmp(buf+6, "JFIF", 4) == 0) {
|
|
id = TC_MAGIC_JPEG;
|
|
goto exit;
|
|
}
|
|
if (cmp_16_bits(buf, 0xFFD8)) {
|
|
id = TC_MAGIC_JPEG;
|
|
goto exit;
|
|
}
|
|
|
|
// WAVE
|
|
if(strncasecmp(buf ,"RIFF",4) ==0 &&
|
|
strncasecmp(buf+8,"WAVE",4) ==0 ) {
|
|
id = TC_MAGIC_WAV;
|
|
goto exit;
|
|
}
|
|
|
|
// CDXA
|
|
if(strncasecmp(buf ,"RIFF",4) ==0 &&
|
|
strncasecmp(buf+8,"CDXA",4) ==0 ) {
|
|
id = TC_MAGIC_CDXA;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 16 byte section
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
if(save_read(buf, 16, off, fdes)) goto exit;
|
|
|
|
//ASF
|
|
if(memcmp(asfhdrguid,buf,16)==0) {
|
|
id = TC_MAGIC_ASF;
|
|
goto exit;
|
|
}
|
|
|
|
//MXF
|
|
if(memcmp(mxfmagic,buf,sizeof(mxfmagic))==0) {
|
|
id = TC_MAGIC_MXF;
|
|
goto exit;
|
|
}
|
|
|
|
// MOV
|
|
|
|
if(strncasecmp(buf+12,"moov", 4) ==0 ||
|
|
strncasecmp(buf+12,"cmov", 4) ==0 ||
|
|
strncasecmp(buf+12,"mdat", 4) ==0 ||
|
|
strncasecmp(buf+12,"pnot", 4) ==0) {
|
|
id = TC_MAGIC_MOV;
|
|
goto exit;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* more tests
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
if(save_read(buf, MAX_PROBE_BYTES, off, fdes)) goto exit;
|
|
|
|
//DV
|
|
cc=scan_header_dv(buf);
|
|
|
|
if(cc==1) {
|
|
id = TC_MAGIC_DV_PAL;
|
|
goto exit;
|
|
}
|
|
|
|
if(cc==2) {
|
|
id = TC_MAGIC_DV_NTSC;
|
|
goto exit;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* exit
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
exit:
|
|
// reset file pointer
|
|
xio_lseek(fdes, 0, SEEK_SET);
|
|
return(id);
|
|
}
|
|
|
|
long streaminfo(int fdes)
|
|
{
|
|
|
|
char buf[64];
|
|
|
|
long id=TC_MAGIC_UNKNOWN;
|
|
|
|
// assume this is a valid file descriptor
|
|
|
|
int bytes=16, ret=0;
|
|
|
|
if( (ret = tc_pread(fdes, buf, bytes))<bytes) {
|
|
if (ret)
|
|
tc_log_error(__FILE__, "File too short (must be 16 bytes at least)");
|
|
else
|
|
tc_log_error(__FILE__, "stream read error: %s", strerror(errno));
|
|
return(TC_MAGIC_ERROR);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 2 byte section
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
// AC3
|
|
|
|
if(cmp_16_bits(buf, TC_MAGIC_AC3)) {
|
|
id = TC_MAGIC_AC3;
|
|
goto exit;
|
|
}
|
|
|
|
// MPEG audio
|
|
|
|
if(cmp_16_bits(buf, TC_MAGIC_MP3)) {
|
|
id = TC_MAGIC_MP3;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf, TC_MAGIC_MP3_2_5)) {
|
|
id = TC_MAGIC_MP3_2_5;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf, TC_MAGIC_MP3_2)) {
|
|
id = TC_MAGIC_MP3_2;
|
|
goto exit;
|
|
}
|
|
|
|
// transport stream
|
|
|
|
if (buf[0] == (uint8_t) TC_MAGIC_TS) {
|
|
id = TC_MAGIC_TS;
|
|
goto exit;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 4 byte section
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
// DTS
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_DTS)) {
|
|
id = TC_MAGIC_DTS;
|
|
goto exit;
|
|
}
|
|
|
|
// VOB
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_VOB)) {
|
|
id = TC_MAGIC_VOB;
|
|
goto exit;
|
|
}
|
|
|
|
// DV
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_DV_NTSC)) {
|
|
id = TC_MAGIC_DV_NTSC;
|
|
goto exit;
|
|
}
|
|
|
|
// DV
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_DV_PAL)) {
|
|
id = TC_MAGIC_DV_PAL;
|
|
goto exit;
|
|
}
|
|
|
|
// M2V
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_M2V)) {
|
|
id = TC_MAGIC_MPEG_ES;
|
|
goto exit;
|
|
}
|
|
|
|
// MPEG Video / .VDR
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_MPEG)) {
|
|
id = TC_MAGIC_MPEG; /* FIXME: it's PES? */
|
|
goto exit;
|
|
}
|
|
|
|
// NUV
|
|
|
|
if(cmp_32_bits(buf, TC_MAGIC_NUV)) {
|
|
id = TC_MAGIC_NUV;
|
|
goto exit;
|
|
}
|
|
|
|
// MP3 audio + odd 0 padding
|
|
|
|
if(cmp_16_bits(buf+1, TC_MAGIC_MP3)) {
|
|
id = TC_MAGIC_MP3;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+1, TC_MAGIC_MP3_2_5)) {
|
|
id = TC_MAGIC_MP3_2_5;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+1, TC_MAGIC_MP3_2)) {
|
|
id = TC_MAGIC_MP3_2;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+2, TC_MAGIC_MP3)) {
|
|
id = TC_MAGIC_MP3;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+2, TC_MAGIC_MP3_2_5)) {
|
|
id = TC_MAGIC_MP3_2_5;
|
|
goto exit;
|
|
}
|
|
|
|
if(cmp_16_bits(buf+2, TC_MAGIC_MP3_2)) {
|
|
id = TC_MAGIC_MP3_2;
|
|
goto exit;
|
|
}
|
|
|
|
// transport stream
|
|
|
|
if (cmp_16_bits(buf, TC_MAGIC_TS)) {
|
|
id = TC_MAGIC_TS;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 8 byte section
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
// YUV4MPEG
|
|
|
|
if (strncmp (buf, "YUV4MPEG", 8)==0) {
|
|
id = TC_MAGIC_YUV4MPEG;
|
|
goto exit;
|
|
}
|
|
|
|
// MOV
|
|
|
|
if(strncasecmp(buf+4,"moov", 4) ==0 ||
|
|
strncasecmp(buf+4,"cmov", 4) ==0 ||
|
|
strncasecmp(buf+4,"mdat", 4) ==0 ||
|
|
strncasecmp(buf+4,"pnot", 4) ==0) {
|
|
id = TC_MAGIC_MOV;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 12 byte section
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
// WAVE
|
|
if(strncasecmp(buf ,"RIFF",4) ==0 &&
|
|
strncasecmp(buf+8,"WAVE",4) ==0 ) {
|
|
id = TC_MAGIC_WAV;
|
|
goto exit;
|
|
}
|
|
|
|
// OGG
|
|
|
|
if (strncasecmp(buf, "OggS", 4) == 0) {
|
|
id = TC_MAGIC_OGG;
|
|
goto exit;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* 16 byte section
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
if(memcmp(asfhdrguid,buf,16)==0) {
|
|
id = TC_MAGIC_ASF;
|
|
goto exit;
|
|
}
|
|
|
|
//MXF
|
|
if(memcmp(mxfmagic,buf,sizeof(mxfmagic))==0) {
|
|
id = TC_MAGIC_MXF;
|
|
goto exit;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------
|
|
*
|
|
* exit
|
|
*
|
|
*-------------------------------------------------------------------*/
|
|
|
|
exit:
|
|
|
|
return(id);
|
|
}
|
|
|
|
const char *filetype(uint32_t magic)
|
|
{
|
|
|
|
switch(magic) {
|
|
|
|
case TC_MAGIC_TS: return("MPEG transport stream (TS)");
|
|
case TC_MAGIC_MPEG_PS: /* fallthrough */
|
|
case TC_MAGIC_VOB: return("MPEG program stream (PS)");
|
|
case TC_MAGIC_MPEG_ES: /* fallthrough */
|
|
case TC_MAGIC_M2V: return("MPEG elementary stream (ES)");
|
|
case TC_MAGIC_MPEG_PES: /* fallthrough */
|
|
case TC_MAGIC_MPEG: return("MPEG packetized elementary stream (PES)");
|
|
case TC_MAGIC_AVI: return("RIFF data, AVI video");
|
|
case TC_MAGIC_WAV: return("RIFF data, WAVE audio");
|
|
case TC_MAGIC_CDXA: return("RIFF data, CDXA");
|
|
case TC_MAGIC_MOV: return("Apple QuickTime movie file");
|
|
case TC_MAGIC_ASF: return("advanced streaming format ASF");
|
|
case TC_MAGIC_TIFF1:
|
|
case TC_MAGIC_TIFF2: return("TIFF image");
|
|
case TC_MAGIC_JPEG: return("JPEG image");
|
|
case TC_MAGIC_BMP: return("BMP image");
|
|
case TC_MAGIC_PNG: return("PNG image");
|
|
case TC_MAGIC_GIF: return("GIF image");
|
|
case TC_MAGIC_PPM: return("PPM image");
|
|
case TC_MAGIC_PGM: return("PGM image");
|
|
case TC_MAGIC_SGI: return("SGI image");
|
|
case TC_MAGIC_RMF: return("Real Media");
|
|
case TC_MAGIC_XML: return("XML file, need to analyze the content");
|
|
case TC_MAGIC_MXF: return("The Material eXchange Format");
|
|
case TC_MAGIC_OGG: return("OGG Multimedia Container");
|
|
|
|
case TC_MAGIC_RAW: return("RAW stream");
|
|
case TC_MAGIC_AC3: return("AC3 stream");
|
|
case TC_MAGIC_DTS: return("DTS stream");
|
|
case TC_MAGIC_MP3: return("MPEG-1 layer-3 stream");
|
|
case TC_MAGIC_MP3_2: return("MPEG-2 layer-3 stream");
|
|
case TC_MAGIC_MP3_2_5: return("MPEG-2.5 layer-3 stream");
|
|
case TC_MAGIC_MP2: return("MP2 stream");
|
|
case TC_MAGIC_ID3: return("MPEG audio ID3 tag");
|
|
|
|
case TC_MAGIC_DV_NTSC: return("Digital Video (NTSC)");
|
|
case TC_MAGIC_DV_PAL: return("Digital Video (PAL)");
|
|
case TC_MAGIC_DVD: return("DVD image/device");
|
|
case TC_MAGIC_DVD_PAL: return("PAL DVD image/device");
|
|
case TC_MAGIC_DVD_NTSC: return("NTSC DVD image/device");
|
|
case TC_MAGIC_YUV4MPEG: return("YUV4MPEG stream");
|
|
case TC_MAGIC_NUV: return("NuppelVideo stream");
|
|
case TC_MAGIC_VNC: return("VNCrec logfile");
|
|
case TC_MAGIC_PV3: return("PV3 video");
|
|
|
|
case TC_MAGIC_V4L_AUDIO: return("V4L audio device");
|
|
case TC_MAGIC_V4L_VIDEO: return("V4L video device");
|
|
case TC_MAGIC_BKTR_VIDEO: return("bktr video device");
|
|
case TC_MAGIC_SUNAU_AUDIO: return("sunau audio device");
|
|
case TC_MAGIC_BSDAV: return("bsdav stream");
|
|
case TC_MAGIC_OSS_AUDIO: return("OSS audio device");
|
|
case TC_MAGIC_PIPE: return("pipe/fifo (not seekable)");
|
|
case TC_MAGIC_MPLAYER: return("probed by mplayer");
|
|
case TC_MAGIC_X11: return("X11 display source");
|
|
case TC_MAGIC_ERROR: return("error");
|
|
case TC_MAGIC_UNKNOWN:
|
|
default: return("unknown file type");
|
|
}
|
|
}
|
|
|
|
static int scan_header_dv(const char *buf)
|
|
{
|
|
int cc = -1;
|
|
#ifdef HAVE_LIBDV
|
|
dv_decoder_t *dv_decoder = dv_decoder_new(TRUE, FALSE, FALSE);
|
|
|
|
// Initialize DV decoder
|
|
|
|
if (dv_decoder == NULL) {
|
|
tc_log_error(__FILE__, "dv decoder init failed");
|
|
return(-1);
|
|
}
|
|
|
|
dv_decoder->prev_frame_decoded = 0;
|
|
cc = dv_parse_header(dv_decoder, buf);
|
|
|
|
dv_decoder_free(dv_decoder);
|
|
#endif
|
|
return(cc);
|
|
}
|
|
|