mirror of
https://github.com/panzi/mediaextract
synced 2025-02-17 13:07:24 +00:00
bugfixes and ID3 support
This commit is contained in:
parent
8debf03fb9
commit
82890cf759
7
Makefile
7
Makefile
@ -1,5 +1,5 @@
|
||||
BUILDDIR=build
|
||||
OBJ=$(BUILDDIR)/audioextract.o $(BUILDDIR)/wave.o $(BUILDDIR)/ogg.o $(BUILDDIR)/mpeg.o
|
||||
OBJ=$(BUILDDIR)/audioextract.o $(BUILDDIR)/wave.o $(BUILDDIR)/ogg.o $(BUILDDIR)/mpeg.o $(BUILDDIR)/id3.o
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -std=c99 -O2 -fmessage-length=0 -g
|
||||
BIN=$(BUILDDIR)/audioextract
|
||||
@ -11,7 +11,7 @@ all: $(BIN)
|
||||
$(BIN): $(OBJ)
|
||||
$(CC) $(CFLAGS) $(OBJ) -o $@
|
||||
|
||||
$(BUILDDIR)/audioextract.o: audioextract.c audioextract.h ogg.h wave.h mpeg.h
|
||||
$(BUILDDIR)/audioextract.o: audioextract.c audioextract.h ogg.h wave.h mpeg.h id3.h
|
||||
$(CC) $(CFLAGS) $< -o $@ -c
|
||||
|
||||
$(BUILDDIR)/wave.o: wave.c audioextract.h wave.h
|
||||
@ -23,5 +23,8 @@ $(BUILDDIR)/ogg.o: ogg.c audioextract.h ogg.h
|
||||
$(BUILDDIR)/mpeg.o: mpeg.c audioextract.h mpeg.h
|
||||
$(CC) $(CFLAGS) $< -o $@ -c
|
||||
|
||||
$(BUILDDIR)/id3.o: id3.c audioextract.h id3.h
|
||||
$(CC) $(CFLAGS) $< -o $@ -c
|
||||
|
||||
clean:
|
||||
rm $(BIN) $(OBJ)
|
||||
|
@ -12,13 +12,15 @@
|
||||
#include "wave.h"
|
||||
#include "ogg.h"
|
||||
#include "mpeg.h"
|
||||
#include "id3.h"
|
||||
|
||||
enum fileformat {
|
||||
NONE,
|
||||
OGG,
|
||||
RIFF,
|
||||
AIFF,
|
||||
MPEG
|
||||
MPEG,
|
||||
ID3v2
|
||||
|
||||
/* TODO: AAC and MKV/WebM? */
|
||||
};
|
||||
@ -53,7 +55,12 @@ const unsigned char *findmagic(const unsigned char *start, const unsigned char *
|
||||
return start;
|
||||
|
||||
default:
|
||||
if (IS_MPEG_MAGIC(start))
|
||||
if (IS_ID3v2_MAGIC(start))
|
||||
{
|
||||
*format = ID3v2;
|
||||
return start;
|
||||
}
|
||||
else if (IS_MPEG_MAGIC(start))
|
||||
{
|
||||
*format = MPEG;
|
||||
return start;
|
||||
@ -185,8 +192,17 @@ int extract(const char *filepath, size_t *numfilesptr)
|
||||
}
|
||||
break;
|
||||
|
||||
case ID3v2:
|
||||
case MPEG:
|
||||
if (mpeg_isframe(ptr, end, &mpeg))
|
||||
if (format == ID3v2)
|
||||
{
|
||||
if (!id3v2_istag(ptr, end, &length))
|
||||
break;
|
||||
}
|
||||
else
|
||||
length = 0;
|
||||
|
||||
if (mpeg_isframe(ptr + length, end, &mpeg))
|
||||
{
|
||||
uint8_t version = mpeg.version;
|
||||
uint8_t layer = mpeg.layer;
|
||||
@ -197,6 +213,9 @@ int extract(const char *filepath, size_t *numfilesptr)
|
||||
layer == 3 ? "mp3" :
|
||||
"mpeg");
|
||||
|
||||
write(outfd, ptr, length);
|
||||
ptr += length;
|
||||
|
||||
do {
|
||||
write(outfd, ptr, mpeg.frame_size);
|
||||
ptr += mpeg.frame_size;
|
||||
@ -204,6 +223,19 @@ int extract(const char *filepath, size_t *numfilesptr)
|
||||
&& mpeg_isframe(ptr, end, &mpeg)
|
||||
&& mpeg.version == version
|
||||
&& mpeg.layer == layer);
|
||||
|
||||
if (id3v1_istag(ptr, end, &length))
|
||||
{
|
||||
write(outfd, ptr, length);
|
||||
ptr += length;
|
||||
}
|
||||
|
||||
if (id3v2_istag(ptr, end, &length))
|
||||
{
|
||||
write(outfd, ptr, length);
|
||||
ptr += length;
|
||||
}
|
||||
|
||||
close(outfd);
|
||||
continue;
|
||||
}
|
||||
|
46
id3.c
Normal file
46
id3.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "id3.h"
|
||||
|
||||
int id3v1_istag(const unsigned char *start, const unsigned char *end, size_t *lengthptr)
|
||||
{
|
||||
if ((intptr_t)end <= ID3v1_TAG_SIZE || end - ID3v1_TAG_SIZE < start)
|
||||
return 0;
|
||||
|
||||
if (!IS_ID3v1_MAGIC(start))
|
||||
return 0;
|
||||
|
||||
if (lengthptr) *lengthptr = ID3v1_TAG_SIZE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int id3v2_istag(const unsigned char *start, const unsigned char *end, size_t *lengthptr)
|
||||
{
|
||||
if ((intptr_t)end <= ID3v2_HEADER_SIZE || end - ID3v2_HEADER_SIZE < start)
|
||||
return 0;
|
||||
|
||||
if (!IS_ID3v2_MAGIC(start))
|
||||
return 0;
|
||||
|
||||
uint8_t major = start[3];
|
||||
uint8_t minor = start[4];
|
||||
uint8_t flags = start[5];
|
||||
uint32_t size = ((start[6] & 0x7f) << 21)
|
||||
| ((start[7] & 0x7f) << 14)
|
||||
| ((start[8] & 0x7f) << 7)
|
||||
| (start[9] & 0x7f);
|
||||
if (major == 0xff || major < 2 || minor == 0xff || *(uint32_t *)(start + 6) & 0x80808080)
|
||||
return 0;
|
||||
|
||||
size_t length = size + ID3v2_HEADER_SIZE;
|
||||
|
||||
/* has footer? */
|
||||
if (flags & 0x10)
|
||||
length += ID3v2_FOOTER_SIZE;
|
||||
|
||||
if ((intptr_t)end <= length || end - length < start)
|
||||
return 0;
|
||||
|
||||
if (lengthptr) *lengthptr = length;
|
||||
|
||||
return 1;
|
||||
}
|
33
id3.h
Normal file
33
id3.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef AUDIOEXTRACT_ID3_H__
|
||||
#define AUDIOEXTRACT_ID3_H__
|
||||
|
||||
#include "audioextract.h"
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
|
||||
# define ID3_MASK (uint32_t)0x00FFFFFF
|
||||
# define ID3v1_MAGIC (uint32_t)0x00474154 /* "TAG\0" (reversed) */
|
||||
# define ID3v2_MAGIC (uint32_t)0x00334449 /* "ID3\0" (reversed) */
|
||||
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
|
||||
# define ID3_MASK (uint32_t)0xFFFFFF00
|
||||
# define ID3v1_MAGIC (uint32_t)0x54414700 /* "TAG\0" */
|
||||
# define ID3v2_MAGIC (uint32_t)0x49443300 /* "ID3\0" */
|
||||
|
||||
#else
|
||||
|
||||
# error unsupported endian
|
||||
|
||||
#endif
|
||||
|
||||
#define IS_ID3v1_MAGIC(hdr) ((*(uint32_t *)(hdr) & ID3_MASK) == ID3v1_MAGIC)
|
||||
#define IS_ID3v2_MAGIC(hdr) ((*(uint32_t *)(hdr) & ID3_MASK) == ID3v2_MAGIC)
|
||||
#define ID3v1_TAG_SIZE 128
|
||||
#define ID3v2_HEADER_SIZE 10
|
||||
#define ID3v2_FOOTER_SIZE 10
|
||||
|
||||
int id3v1_istag(const unsigned char *start, const unsigned char *end, size_t *lengthptr);
|
||||
int id3v2_istag(const unsigned char *start, const unsigned char *end, size_t *lengthptr);
|
||||
|
||||
#endif /* AUDIOEXTRACT_ID3_H__ */
|
3
mpeg.c
3
mpeg.c
@ -79,6 +79,9 @@ int mpeg_isframe(const unsigned char *start, const unsigned char *end, struct mp
|
||||
uint32_t samprate = mpeg_srates[ver][srx];
|
||||
uint16_t samples = mpeg_frame_samples[ver][lyr];
|
||||
uint8_t slot_size = mpeg_slot_size[lyr];
|
||||
|
||||
if (bitrate == 0 || samprate == 0 || samples == 0)
|
||||
return 0;
|
||||
|
||||
// In-between calculations
|
||||
// Frame sizes are truncated integers
|
||||
|
Loading…
Reference in New Issue
Block a user