mirror of
https://github.com/panzi/mediaextract
synced 2025-02-19 05:56:51 +00:00
GIF support and new MAGIC magic that compiles to immediate values
This commit is contained in:
parent
b478068a4e
commit
7794518c0a
9
Makefile
9
Makefile
@ -26,7 +26,8 @@ OBJ=\
|
||||
$(BUILDDIR)/smk.o \
|
||||
$(BUILDDIR)/bmp.o \
|
||||
$(BUILDDIR)/png.o \
|
||||
$(BUILDDIR)/jpg.o
|
||||
$(BUILDDIR)/jpg.o \
|
||||
$(BUILDDIR)/gif.o
|
||||
CC=gcc
|
||||
LD=$(CC)
|
||||
COMMON_CFLAGS=-Wall -Werror -Wextra -std=gnu99 -O2 -g $(INCLUDE) $(LIBDIRS) -D_FILE_OFFSET_BITS=64
|
||||
@ -96,7 +97,8 @@ $(BUILDDIR)/mediaextract.o: src/mediaextract.c \
|
||||
src/smk.h \
|
||||
src/bmp.h \
|
||||
src/png.h \
|
||||
src/jpg.h
|
||||
src/jpg.h \
|
||||
src/gif.h
|
||||
$(CC) $(CFLAGS) $< -o $@ -c $(LIBS)
|
||||
|
||||
$(BUILDDIR)/mediaextract_$(PLATFORM).o: src/mediaextract_$(PLATFORM).c src/mediaextract.h
|
||||
@ -156,6 +158,9 @@ $(BUILDDIR)/png.o: src/png.c src/mediaextract.h src/png.h
|
||||
$(BUILDDIR)/jpg.o: src/jpg.c src/mediaextract.h src/jpg.h
|
||||
$(CC) $(CFLAGS) $< -o $@ -c $(LIBS)
|
||||
|
||||
$(BUILDDIR)/gif.o: src/gif.c src/mediaextract.h src/gif.h
|
||||
$(CC) $(CFLAGS) $< -o $@ -c $(LIBS)
|
||||
|
||||
ifeq ($(PLATFORM),posix)
|
||||
install: $(PREFIX)/bin/$(APPNAME)
|
||||
|
||||
|
13
README.md
13
README.md
@ -20,7 +20,10 @@ Or (uses `x86_64-w64-mingw32-gcc`):
|
||||
make TARGET=win64 builddir
|
||||
make TARGET=win64
|
||||
|
||||
**NOTE:** 32bit binaries can only process 2 GB of a file at once. The rest of
|
||||
**Warning:** This program only works correctly on platforms that allow unaligned
|
||||
memory access (e.g. x86 and ARM, although it might be quite slow on the latter).
|
||||
|
||||
**Note:** 32bit binaries can only process 2 GB of a file at once. The rest of
|
||||
bigger files will be ignored. You need to run this program several times with
|
||||
different `--offset` values to process such a file whole.
|
||||
|
||||
@ -90,10 +93,11 @@ files.
|
||||
Supported formats:
|
||||
all all supported formats
|
||||
default the default set of formats (AIFF, ASF, AU, BINK, BMP,
|
||||
ID3v2, IT, JPG, MIDI, MP4, Ogg, PNG, RIFF, S3M, SMK, XM)
|
||||
GIF, ID3v2, IT, JPG, MIDI, MP4, Ogg, PNG, RIFF, S3M,
|
||||
SMK, XM)
|
||||
audio all audio files (AIFF, ASF, AU, ID3v2, IT, MIDI, MP4,
|
||||
Ogg, RIFF, S3M, XM)
|
||||
image all image files (BMP, PNG, JPG)
|
||||
image all image files (BMP, PNG, JPG, GIF)
|
||||
tracker all tracker files (MOD, S3M, IT, XM)
|
||||
video all video files (ASF, BINK, MP4, RIFF, SMK)
|
||||
|
||||
@ -102,6 +106,7 @@ files.
|
||||
au Sun Microsystems audio file format (.au or .snd)
|
||||
bink BINK files
|
||||
bmp Windows Bitmap files
|
||||
gif Graphics Interchange Format files
|
||||
id3v2 MPEG layer 1/2/3 files with ID3v2 tags
|
||||
it ImpulseTracker files
|
||||
jpg JPEG Interchange Format files
|
||||
@ -110,7 +115,7 @@ files.
|
||||
mpg123 MPEG layer 1/2/3 files (MP1, MP2, MP3)
|
||||
mp4 MP4 files (M4A, M4V, 3GPP etc.)
|
||||
ogg Ogg files (Vorbis, Opus, Theora, etc.)
|
||||
png Portable Network Graphics file
|
||||
png Portable Network Graphics files
|
||||
riff Resource Interchange File Format files (ANI, AVI, MMM,
|
||||
PAL, RDI, RMI, WAV)
|
||||
s3m ScreamTracker III files
|
||||
|
110
src/gif.c
Normal file
110
src/gif.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include "gif.h"
|
||||
|
||||
// See: http://www.onicos.com/staff/iz/formats/gif.html
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct gif_header {
|
||||
uint8_t signature[GIF_SIGNATURE_SIZE];
|
||||
uint16_t screenwidth;
|
||||
uint16_t screenheight;
|
||||
uint8_t flags;
|
||||
uint8_t bgcolorindex;
|
||||
uint8_t pxaspect;
|
||||
};
|
||||
|
||||
struct gif_image_block {
|
||||
uint8_t mark;
|
||||
uint16_t left;
|
||||
uint16_t top;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint8_t flags;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
int gif_isfile(const uint8_t *data, size_t input_len, size_t *lengthptr)
|
||||
{
|
||||
if (input_len < GIF_MIN_SIZE || (
|
||||
memcmp(data, GIF87a_SIGNATURE, GIF_SIGNATURE_SIZE) != 0 &&
|
||||
memcmp(data, GIF89a_SIGNATURE, GIF_SIGNATURE_SIZE) != 0))
|
||||
return 0;
|
||||
|
||||
const struct gif_header *header = (const struct gif_header *)data;
|
||||
size_t length = GIF_HEADER_SIZE;
|
||||
|
||||
if (header->flags & GIF_CT_FLAG)
|
||||
length += (2 << (header->flags & 7)) * 3;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (length > input_len - 1)
|
||||
return 0;
|
||||
|
||||
unsigned int marker = data[length];
|
||||
|
||||
if (marker == GIF_IMAGE_BLOCK)
|
||||
{
|
||||
if (length > input_len - GIF_IMAGE_BLOCK_SIZE)
|
||||
return 0;
|
||||
|
||||
const struct gif_image_block *image = (struct gif_image_block *)(data + length);
|
||||
length += GIF_IMAGE_BLOCK_SIZE;
|
||||
|
||||
if (image->flags & GIF_CT_FLAG)
|
||||
{
|
||||
size_t tblsize = (2 << (image->flags & 15)) * 3;
|
||||
|
||||
if (SIZE_MAX - tblsize < length)
|
||||
return 0;
|
||||
|
||||
length += tblsize;
|
||||
|
||||
if (length > input_len)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (marker == GIF_EXT)
|
||||
{
|
||||
if (length > input_len - 2)
|
||||
return 0;
|
||||
length += 2;
|
||||
}
|
||||
else if (marker == GIF_TRAILER)
|
||||
{
|
||||
++ length;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// parse data blocks until terminator (block of size 0)
|
||||
for (;;)
|
||||
{
|
||||
size_t size = data[length];
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
if (length == SIZE_MAX)
|
||||
return 0;
|
||||
|
||||
++ length;
|
||||
break;
|
||||
}
|
||||
else if (SIZE_MAX - (size + 1) < length)
|
||||
return 0;
|
||||
|
||||
|
||||
length += size + 1;
|
||||
|
||||
if (length > input_len)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (lengthptr)
|
||||
*lengthptr = length;
|
||||
|
||||
return 1;
|
||||
}
|
23
src/gif.h
Normal file
23
src/gif.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef MEDIAEXTRACT_GIF_H__
|
||||
#define MEDIAEXTRACT_GIF_H__
|
||||
|
||||
#include "mediaextract.h"
|
||||
|
||||
#define GIF87a_SIGNATURE "GIF87a"
|
||||
#define GIF89a_SIGNATURE "GIF89a"
|
||||
#define GIF_MAGIC MAGIC(GIF87a_SIGNATURE)
|
||||
#define GIF_SIGNATURE_SIZE 6
|
||||
|
||||
#define GIF_HEADER_SIZE 13
|
||||
#define GIF_IMAGE_BLOCK_SIZE 11
|
||||
#define GIF_MIN_SIZE 14
|
||||
|
||||
#define GIF_IMAGE_BLOCK ','
|
||||
#define GIF_EXT '!'
|
||||
#define GIF_TRAILER ';'
|
||||
|
||||
#define GIF_CT_FLAG 0x80
|
||||
|
||||
int gif_isfile(const uint8_t *data, size_t input_len, size_t *lengthptr);
|
||||
|
||||
#endif /* MEDIAEXTRACT_GIF_H__ */
|
@ -33,6 +33,7 @@
|
||||
#include "bmp.h"
|
||||
#include "png.h"
|
||||
#include "jpg.h"
|
||||
#include "gif.h"
|
||||
|
||||
#if defined(__WINDOWS__) && !defined(__CYGWIN__)
|
||||
# ifdef _WIN64
|
||||
@ -68,15 +69,16 @@ enum fileformat {
|
||||
SMK = 0x4000,
|
||||
BMP = 0x8000,
|
||||
PNG = 0x10000,
|
||||
JPEG = 0x20000
|
||||
JPEG = 0x20000,
|
||||
GIF = 0x40000
|
||||
};
|
||||
|
||||
#define TRACKER_FORMATS (MOD | S3M | IT | XM)
|
||||
#define AUDIO_FORMATS (OGG | RIFF | AIFF | MPG123 | MP4 | ID3v2 | MIDI | MOD | S3M | IT | XM | ASF | AU)
|
||||
#define VIDEO_FORMATS (MP4 | RIFF | ASF | BINK | SMK)
|
||||
#define IMAGE_FORMATS (BMP | PNG | JPEG)
|
||||
#define ALL_FORMATS (OGG | RIFF | AIFF | MPG123 | MP4 | ID3v2 | MIDI | MOD | S3M | IT | XM | ASF | BINK | AU | SMK | BMP | PNG | JPEG)
|
||||
#define DEFAULT_FORMATS (OGG | RIFF | AIFF | MP4 | ID3v2 | MIDI | S3M | IT | XM | ASF | BINK | AU | SMK | BMP | PNG | JPEG)
|
||||
#define IMAGE_FORMATS (BMP | PNG | JPEG | GIF)
|
||||
#define ALL_FORMATS (OGG | RIFF | AIFF | MPG123 | MP4 | ID3v2 | MIDI | MOD | S3M | IT | XM | ASF | BINK | AU | SMK | BMP | PNG | JPEG | GIF)
|
||||
#define DEFAULT_FORMATS (OGG | RIFF | AIFF | MP4 | ID3v2 | MIDI | S3M | IT | XM | ASF | BINK | AU | SMK | BMP | PNG | JPEG | GIF)
|
||||
|
||||
static int usage(int argc, char **argv);
|
||||
static const char *basename(const char *path);
|
||||
@ -148,10 +150,11 @@ static int usage(int argc, char **argv)
|
||||
" Supported formats:\n"
|
||||
" all all supported formats\n"
|
||||
" default the default set of formats (AIFF, ASF, AU, BINK, BMP,\n"
|
||||
" ID3v2, IT, JPG, MIDI, MP4, Ogg, PNG, RIFF, S3M, SMK, XM)\n"
|
||||
" GIF, ID3v2, IT, JPG, MIDI, MP4, Ogg, PNG, RIFF, S3M,\n"
|
||||
" SMK, XM)\n"
|
||||
" audio all audio files (AIFF, ASF, AU, ID3v2, IT, MIDI, MP4,\n"
|
||||
" Ogg, RIFF, S3M, XM)\n"
|
||||
" image all image files (BMP, PNG, JPG)\n"
|
||||
" image all image files (BMP, PNG, JPG, GIF)\n"
|
||||
" tracker all tracker files (MOD, S3M, IT, XM)\n"
|
||||
" video all video files (ASF, BINK, MP4, RIFF, SMK)\n"
|
||||
"\n"
|
||||
@ -160,6 +163,7 @@ static int usage(int argc, char **argv)
|
||||
" au Sun Microsystems audio file format (.au or .snd)\n"
|
||||
" bink BINK files\n"
|
||||
" bmp Windows Bitmap files\n"
|
||||
" gif Graphics Interchange Format files\n"
|
||||
" id3v2 MPEG layer 1/2/3 files with ID3v2 tags\n"
|
||||
" it ImpulseTracker files\n"
|
||||
" jpg JPEG Interchange Format files\n"
|
||||
@ -168,7 +172,7 @@ static int usage(int argc, char **argv)
|
||||
" mpg123 MPEG layer 1/2/3 files (MP1, MP2, MP3)\n"
|
||||
" mp4 MP4 files (M4A, M4V, 3GPP etc.)\n"
|
||||
" ogg Ogg files (Vorbis, Opus, Theora, etc.)\n"
|
||||
" png Portable Network Graphics file\n"
|
||||
" png Portable Network Graphics files\n"
|
||||
" riff Resource Interchange File Format files (ANI, AVI, MMM,\n"
|
||||
" PAL, RDI, RMI, WAV)\n"
|
||||
" s3m ScreamTracker III files\n"
|
||||
@ -445,7 +449,14 @@ int do_extract(const uint8_t *filedata, size_t filesize, const struct extract_op
|
||||
ptr += length;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (formats & GIF && magic == GIF_MAGIC && gif_isfile(ptr, input_len, &length))
|
||||
{
|
||||
WRITE_FILE(ptr, length, "gif");
|
||||
ptr += length;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (formats & JPEG && IS_JPG_MAGIC(magic) && jpg_isfile(ptr, input_len, &length))
|
||||
{
|
||||
WRITE_FILE(ptr, length, "jpg");
|
||||
@ -613,6 +624,10 @@ int parse_formats(const char *formats)
|
||||
{
|
||||
mask = JPEG;
|
||||
}
|
||||
else if (strncasecmp("gif", start, len) == 0)
|
||||
{
|
||||
mask = GIF;
|
||||
}
|
||||
else if (strncasecmp("audio", start, len) == 0)
|
||||
{
|
||||
mask = AUDIO_FORMATS;
|
||||
|
@ -35,6 +35,11 @@
|
||||
# define be64toh OSSwapBigToHostInt64
|
||||
# define le64toh OSSwapLittleToHostInt64
|
||||
|
||||
# define __BYTE_ORDER BYTE_ORDER
|
||||
# define __BIG_ENDIAN BIG_ENDIAN
|
||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
# define __PDP_ENDIAN PDP_ENDIAN
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
# include <sys/endian.h>
|
||||
@ -94,13 +99,18 @@
|
||||
|
||||
# else
|
||||
|
||||
# error "byte order not supported"
|
||||
# error byte order not supported
|
||||
|
||||
# endif
|
||||
|
||||
# define __BYTE_ORDER BYTE_ORDER
|
||||
# define __BIG_ENDIAN BIG_ENDIAN
|
||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
# define __PDP_ENDIAN PDP_ENDIAN
|
||||
|
||||
#else
|
||||
|
||||
# error "platform not supported"
|
||||
# error platform not supported
|
||||
|
||||
#endif
|
||||
|
||||
@ -114,7 +124,34 @@
|
||||
|
||||
#endif
|
||||
|
||||
#define _CMAGIC(C1,C2,C3,C4) (uint32_t)(((C1) << 24) | ((C2) << 16) | ((C3) << 8) | (C4))
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
|
||||
# define CMAGIC(C1,C2,C3,C4) _CMAGIC(C4,C3,C2,C1)
|
||||
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
|
||||
# define CMAGIC(C1,C2,C3,C4) _CMAGIC(C1,C2,C3,C4)
|
||||
|
||||
#elif __BYTE_ORDER == __PDP_ENDIAN
|
||||
|
||||
# define CMAGIC(C1,C2,C3,C4) _CMAGIC(C3,C4,C1,C2)
|
||||
|
||||
#else
|
||||
|
||||
# error unsupported byte order
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define MAGIC(STR) (*(const uint32_t*)(STR))
|
||||
#else
|
||||
|
||||
#define _MAGIC(B) CMAGIC((B)[0], (B)[1], (B)[2], (B)[3])
|
||||
#define MAGIC(S) _MAGIC((const uint8_t *)(S))
|
||||
|
||||
#endif
|
||||
|
||||
struct file_info {
|
||||
size_t length;
|
||||
|
192
src/mp4.c
192
src/mp4.c
@ -1,102 +1,108 @@
|
||||
#include "mp4.h"
|
||||
|
||||
struct ftyp {
|
||||
const char *brand;
|
||||
uint32_t brand;
|
||||
const char *ext;
|
||||
};
|
||||
|
||||
static const struct ftyp mp4_ftyps[] = {
|
||||
{ "3g2a", "3g2" },
|
||||
{ "3g2b", "3g2" },
|
||||
{ "3g2c", "3g2" },
|
||||
{ "3ge6", "3gp" },
|
||||
{ "3ge7", "3gp" },
|
||||
{ "3gg6", "3gp" },
|
||||
{ "3gp1", "3gp" },
|
||||
{ "3gp2", "3gp" },
|
||||
{ "3gp3", "3gp" },
|
||||
{ "3gp4", "3gp" },
|
||||
{ "3gp5", "3gp" },
|
||||
{ "3gp6", "3gp" },
|
||||
{ "3gp6", "3gp" },
|
||||
{ "3gp6", "3gp" },
|
||||
{ "3gs7", "3gp" },
|
||||
{ "avc1", 0 },
|
||||
{ "CAEP", 0 },
|
||||
{ "caqv", 0 },
|
||||
{ "CDes", 0 },
|
||||
{ "da0a", 0 },
|
||||
{ "da0b", 0 },
|
||||
{ "da1a", 0 },
|
||||
{ "da1b", 0 },
|
||||
{ "da2a", 0 },
|
||||
{ "da2b", 0 },
|
||||
{ "da3a", 0 },
|
||||
{ "da3b", 0 },
|
||||
{ "dmb1", 0 },
|
||||
{ "dmpf", 0 },
|
||||
{ "drc1", "mp4" },
|
||||
{ "dv1a", 0 },
|
||||
{ "dv1b", 0 },
|
||||
{ "dv2a", 0 },
|
||||
{ "dv2b", 0 },
|
||||
{ "dv3a", 0 },
|
||||
{ "dv3b", 0 },
|
||||
{ "dvr1", "dvb" },
|
||||
{ "dvt1", "dvb" },
|
||||
{ "F4V ", "f4v" },
|
||||
{ "F4P ", "f4p" },
|
||||
{ "F4A ", "f4a" },
|
||||
{ "F4B ", "f4b" },
|
||||
{ "isc2", 0 },
|
||||
{ "iso2", "mp4" },
|
||||
{ "isom", "mp4" },
|
||||
{ "JP2 ", "jp2" },
|
||||
{ "JP20", "jp2" },
|
||||
{ "jpm ", "jpm" },
|
||||
{ "jpx ", "jpx" },
|
||||
{ "KDDI", "3gp" },
|
||||
{ "M4A ", "m4a" },
|
||||
{ "M4B ", "m4b" },
|
||||
{ "M4P ", "m4p" },
|
||||
{ "M4V ", "m4v" },
|
||||
{ "M4VH", "m4v" },
|
||||
{ "M4VP", "m4v" },
|
||||
{ "mj2s", "jp2" },
|
||||
{ "mjp2", "jp2" },
|
||||
{ "mmp4", "mp4" },
|
||||
{ "mp21", 0 },
|
||||
{ "mp41", "mp4" },
|
||||
{ "mp42", "mp4" },
|
||||
{ "mp71", "mp4" },
|
||||
{ "MPPI", 0 },
|
||||
{ "mqt ", "mqv" },
|
||||
{ "MSNV", "mp4" },
|
||||
{ "NDAS", 0 },
|
||||
{ "NDSC", "mp4" },
|
||||
{ "NDSH", "mp4" },
|
||||
{ "NDSM", "mp4" },
|
||||
{ "NDSP", "mp4" },
|
||||
{ "NDSS", "mp4" },
|
||||
{ "NDXC", "mp4" },
|
||||
{ "NDXH", "mp4" },
|
||||
{ "NDXM", "mp4" },
|
||||
{ "NDXP", "mp4" },
|
||||
{ "NDXS", "mp4" },
|
||||
{ "odcf", 0 },
|
||||
{ "opf2", 0 },
|
||||
{ "opx2", 0 },
|
||||
{ "pana", 0 },
|
||||
{ "qt ", "mov" },
|
||||
{ "ROSS", 0 },
|
||||
{ "sdv ", 0 },
|
||||
{ "ssc1", 0 },
|
||||
{ "ssc2", 0 },
|
||||
{ 0 , 0 }
|
||||
{ CMAGIC('3','g','2','a'), "3g2" },
|
||||
{ CMAGIC('3','g','2','b'), "3g2" },
|
||||
{ CMAGIC('3','g','2','c'), "3g2" },
|
||||
{ CMAGIC('3','g','e','6'), "3gp" },
|
||||
{ CMAGIC('3','g','e','7'), "3gp" },
|
||||
{ CMAGIC('3','g','g','6'), "3gp" },
|
||||
{ CMAGIC('3','g','p','1'), "3gp" },
|
||||
{ CMAGIC('3','g','p','2'), "3gp" },
|
||||
{ CMAGIC('3','g','p','3'), "3gp" },
|
||||
{ CMAGIC('3','g','p','4'), "3gp" },
|
||||
{ CMAGIC('3','g','p','5'), "3gp" },
|
||||
{ CMAGIC('3','g','p','6'), "3gp" },
|
||||
{ CMAGIC('3','g','p','6'), "3gp" },
|
||||
{ CMAGIC('3','g','p','6'), "3gp" },
|
||||
{ CMAGIC('3','g','s','7'), "3gp" },
|
||||
{ CMAGIC('a','v','c','1'), 0 },
|
||||
{ CMAGIC('C','A','E','P'), 0 },
|
||||
{ CMAGIC('c','a','q','v'), 0 },
|
||||
{ CMAGIC('C','D','e','s'), 0 },
|
||||
{ CMAGIC('d','a','0','a'), 0 },
|
||||
{ CMAGIC('d','a','0','b'), 0 },
|
||||
{ CMAGIC('d','a','1','a'), 0 },
|
||||
{ CMAGIC('d','a','1','b'), 0 },
|
||||
{ CMAGIC('d','a','2','a'), 0 },
|
||||
{ CMAGIC('d','a','2','b'), 0 },
|
||||
{ CMAGIC('d','a','3','a'), 0 },
|
||||
{ CMAGIC('d','a','3','b'), 0 },
|
||||
{ CMAGIC('d','m','b','1'), 0 },
|
||||
{ CMAGIC('d','m','p','f'), 0 },
|
||||
{ CMAGIC('d','r','c','1'), "mp4" },
|
||||
{ CMAGIC('d','v','1','a'), 0 },
|
||||
{ CMAGIC('d','v','1','b'), 0 },
|
||||
{ CMAGIC('d','v','2','a'), 0 },
|
||||
{ CMAGIC('d','v','2','b'), 0 },
|
||||
{ CMAGIC('d','v','3','a'), 0 },
|
||||
{ CMAGIC('d','v','3','b'), 0 },
|
||||
{ CMAGIC('d','v','r','1'), "dvb" },
|
||||
{ CMAGIC('d','v','t','1'), "dvb" },
|
||||
{ CMAGIC('F','4','V',' '), "f4v" },
|
||||
{ CMAGIC('F','4','P',' '), "f4p" },
|
||||
{ CMAGIC('F','4','A',' '), "f4a" },
|
||||
{ CMAGIC('F','4','B',' '), "f4b" },
|
||||
{ CMAGIC('i','s','c','2'), 0 },
|
||||
{ CMAGIC('i','s','o','2'), "mp4" },
|
||||
{ CMAGIC('i','s','o','m'), "mp4" },
|
||||
{ CMAGIC('J','P','2',' '), "jp2" },
|
||||
{ CMAGIC('J','P','2','0'), "jp2" },
|
||||
{ CMAGIC('j','p','m',' '), "jpm" },
|
||||
{ CMAGIC('j','p','x',' '), "jpx" },
|
||||
{ CMAGIC('K','D','D','I'), "3gp" },
|
||||
{ CMAGIC('M','4','A',' '), "m4a" },
|
||||
{ CMAGIC('M','4','B',' '), "m4b" },
|
||||
{ CMAGIC('M','4','P',' '), "m4p" },
|
||||
{ CMAGIC('M','4','V',' '), "m4v" },
|
||||
{ CMAGIC('M','4','V','H'), "m4v" },
|
||||
{ CMAGIC('M','4','V','P'), "m4v" },
|
||||
{ CMAGIC('m','j','2','s'), "jp2" },
|
||||
{ CMAGIC('m','j','p','2'), "jp2" },
|
||||
{ CMAGIC('m','m','p','4'), "mp4" },
|
||||
{ CMAGIC('m','p','2','1'), 0 },
|
||||
{ CMAGIC('m','p','4','1'), "mp4" },
|
||||
{ CMAGIC('m','p','4','2'), "mp4" },
|
||||
{ CMAGIC('m','p','7','1'), "mp4" },
|
||||
{ CMAGIC('M','P','P','I'), 0 },
|
||||
{ CMAGIC('m','q','t',' '), "mqv" },
|
||||
{ CMAGIC('M','S','N','V'), "mp4" },
|
||||
{ CMAGIC('N','D','A','S'), 0 },
|
||||
{ CMAGIC('N','D','S','C'), "mp4" },
|
||||
{ CMAGIC('N','D','S','H'), "mp4" },
|
||||
{ CMAGIC('N','D','S','M'), "mp4" },
|
||||
{ CMAGIC('N','D','S','P'), "mp4" },
|
||||
{ CMAGIC('N','D','S','S'), "mp4" },
|
||||
{ CMAGIC('N','D','X','C'), "mp4" },
|
||||
{ CMAGIC('N','D','X','H'), "mp4" },
|
||||
{ CMAGIC('N','D','X','M'), "mp4" },
|
||||
{ CMAGIC('N','D','X','P'), "mp4" },
|
||||
{ CMAGIC('N','D','X','S'), "mp4" },
|
||||
{ CMAGIC('o','d','c','f'), 0 },
|
||||
{ CMAGIC('o','p','f','2'), 0 },
|
||||
{ CMAGIC('o','p','x','2'), 0 },
|
||||
{ CMAGIC('p','a','n','a'), 0 },
|
||||
{ CMAGIC('q','t',' ',' '), "mov" },
|
||||
{ CMAGIC('R','O','S','S'), 0 },
|
||||
{ CMAGIC('s','d','v',' '), 0 },
|
||||
{ CMAGIC('s','s','c','1'), 0 },
|
||||
{ CMAGIC('s','s','c','2'), 0 },
|
||||
{ 0 , 0 }
|
||||
};
|
||||
|
||||
static const char *mp4_bodyatom_types[] = {
|
||||
"moov", "mdat", "free", "skip", "wide", "pnot", 0
|
||||
static const uint32_t mp4_bodyatom_types[] = {
|
||||
CMAGIC('m','o','o','v'),
|
||||
CMAGIC('m','d','a','t'),
|
||||
CMAGIC('f','r','e','e'),
|
||||
CMAGIC('s','k','i','p'),
|
||||
CMAGIC('w','i','d','e'),
|
||||
CMAGIC('p','n','o','t'),
|
||||
0
|
||||
};
|
||||
|
||||
struct mp4_atom_head {
|
||||
@ -116,7 +122,7 @@ static const char *mp4_find_ext(uint32_t brand)
|
||||
{
|
||||
for (const struct ftyp *ftyp = mp4_ftyps; ftyp->brand; ++ ftyp)
|
||||
{
|
||||
if (MAGIC(ftyp->brand) == brand)
|
||||
if (ftyp->brand == brand)
|
||||
{
|
||||
if (!ftyp->ext) return "mp4";
|
||||
return ftyp->ext;
|
||||
@ -127,9 +133,9 @@ static const char *mp4_find_ext(uint32_t brand)
|
||||
|
||||
static int mp4_isbodyatom_type(uint32_t type)
|
||||
{
|
||||
for (const char **atom = mp4_bodyatom_types; *atom; ++ atom)
|
||||
for (const uint32_t *atom = mp4_bodyatom_types; *atom; ++ atom)
|
||||
{
|
||||
if (MAGIC(atom) == type)
|
||||
if (*atom == type)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
38
src/riff.c
38
src/riff.c
@ -3,7 +3,7 @@
|
||||
/* see: http://www.johnloomis.org/cpe102/asgn/asgn1/riff.html */
|
||||
|
||||
struct riff_chunk_spec {
|
||||
const char *type;
|
||||
uint32_t type;
|
||||
const struct riff_chunk_spec *body;
|
||||
int required;
|
||||
};
|
||||
@ -19,7 +19,7 @@ static const struct riff_chunk_spec riff_empty_body[] = {
|
||||
|
||||
/* WAVE */
|
||||
static const struct riff_chunk_spec riff_wav_body[] = {
|
||||
{ "fmt ", 0, 1 },
|
||||
{ CMAGIC('f','m','t',' '), 0, 1 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
@ -27,43 +27,43 @@ static const struct riff_chunk_spec riff_wav_body[] = {
|
||||
// TODO: AVI 2.0? only makes sense for files > 4 GB
|
||||
// http://www.the-labs.com/Video/odmlff2-avidef.pdf
|
||||
static const struct riff_chunk_spec riff_avi_hdrl_body[] = {
|
||||
{ "avih", 0, 1 },
|
||||
{ CMAGIC('a','v','i','h'), 0, 1 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const struct riff_chunk_spec riff_avi_body[] = {
|
||||
{ "hdrl", 0, 1 },
|
||||
{ "movi", 0, 1 },
|
||||
{ CMAGIC('h','d','r','l'), 0, 1 },
|
||||
{ CMAGIC('m','o','v','i'), 0, 1 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
/* ACON */
|
||||
static const struct riff_chunk_spec riff_ani_fram_body[] = {
|
||||
{ "icon", 0, 1 },
|
||||
{ CMAGIC('i','c','o','n'), 0, 1 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const struct riff_chunk_spec riff_ani_body[] = {
|
||||
{ "INFO", riff_empty_body, 0 },
|
||||
{ "anih", 0, 1 },
|
||||
{ "fram", riff_ani_fram_body, 1 },
|
||||
{ CMAGIC('I','N','F','O'), riff_empty_body, 0 },
|
||||
{ CMAGIC('a','n','i','h'), 0, 1 },
|
||||
{ CMAGIC('f','r','a','m'), riff_ani_fram_body, 1 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
/* PAL */
|
||||
static const struct riff_chunk_spec riff_pal_body[] = {
|
||||
{ "data", 0, 1 },
|
||||
{ CMAGIC('d','a','t','a'), 0, 1 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const struct riff_file_spec riff_file_specs[] = {
|
||||
{ { "WAVE", riff_wav_body, 1 }, "wav" },
|
||||
{ { "AVI ", riff_avi_body, 1 }, "avi" },
|
||||
{ { "ACON", riff_ani_body, 1 }, "ani" },
|
||||
{ { "RMID", riff_empty_body, 1 }, "rmi" },
|
||||
{ { "PAL ", riff_pal_body, 1 }, "pal" },
|
||||
{ { "RDIB", riff_empty_body, 1 }, "rdi" },
|
||||
{ { "RMMP", riff_empty_body, 1 }, "mmm" },
|
||||
{ { CMAGIC('W','A','V','E'), riff_wav_body, 1 }, "wav" },
|
||||
{ { CMAGIC('A','V','I',' '), riff_avi_body, 1 }, "avi" },
|
||||
{ { CMAGIC('A','C','O','N'), riff_ani_body, 1 }, "ani" },
|
||||
{ { CMAGIC('R','M','I','D'), riff_empty_body, 1 }, "rmi" },
|
||||
{ { CMAGIC('P','A','L',' '), riff_pal_body, 1 }, "pal" },
|
||||
{ { CMAGIC('R','D','I','B'), riff_empty_body, 1 }, "rdi" },
|
||||
{ { CMAGIC('R','M','M','P'), riff_empty_body, 1 }, "mmm" },
|
||||
{ { 0, 0, 0 }, 0 }
|
||||
};
|
||||
|
||||
@ -78,7 +78,7 @@ const uint8_t *riff_match(const uint8_t *data, size_t size,
|
||||
uint32_t chunk_size = le32toh(*(const uint32_t *)(data + 4));
|
||||
uint32_t type = MAGIC(data + 8);
|
||||
|
||||
if (type != MAGIC(spec->type))
|
||||
if (type != spec->type)
|
||||
return NULL;
|
||||
|
||||
if (chunk_size > size - 8)
|
||||
@ -164,7 +164,7 @@ const uint8_t *riff_match(const uint8_t *data, size_t size,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size < 8 || MAGIC(data) != MAGIC(spec->type))
|
||||
if (size < 8 || MAGIC(data) != spec->type)
|
||||
return NULL;
|
||||
|
||||
uint32_t chunk_size = le32toh(*(const uint32_t *)(data + 4));
|
||||
|
Loading…
Reference in New Issue
Block a user