#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 4096
// Function to find the next occurrence of a marker
long find_marker(FILE *file, const unsigned char *marker, size_t marker_len) {
unsigned char buffer[BUFFER_SIZE];
size_t bytes_read;
long pos = ftell(file);
// Seek to the start of the file (position is already at the right place)
fseek(file, pos, SEEK_SET);
while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, file)) > 0) {
for (size_t i = 0; i <= bytes_read - marker_len; i++) {
if (memcmp(buffer + i, marker, marker_len) == 0) {
return ftell(file) - bytes_read + i;
}
}
}
return -1;
}
// Function to extract the MP4 segment
void extract_mp4(const char *input_filename, long start, long end, const char *output_filename) {
FILE *input_fh = fopen(input_filename, "rb");
if (!input_fh) {
perror("Cannot open input file");
exit(EXIT_FAILURE);
}
FILE *output_fh = fopen(output_filename, "wb");
if (!output_fh) {
perror("Cannot open output file");
fclose(input_fh);
exit(EXIT_FAILURE);
}
fseek(input_fh, start, SEEK_SET);
long length = end - start;
unsigned char buffer[BUFFER_SIZE];
while (length > 0) {
size_t bytes_to_read = (length < BUFFER_SIZE) ? length : BUFFER_SIZE;
size_t bytes_read = fread(buffer, 1, bytes_to_read, input_fh);
if (bytes_read > 0) {
fwrite(buffer, 1, bytes_read, output_fh);
length -= bytes_read;
}
}
fclose(input_fh);
fclose(output_fh);
}
// Function to get the basename without the extension
void get_basename_without_extension(const char *input_filename, char *basename) {
const char *dot_pos = strrchr(input_filename, '.');
if (dot_pos) {
size_t len = dot_pos - input_filename;
strncpy(basename, input_filename, len);
basename[len] = '\0';
} else {
strcpy(basename, input_filename);
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <input_filename>\n", argv[0]);
return EXIT_FAILURE;
}
const char *input_filename = argv[1];
unsigned char start_marker[] = { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79 }; // 'ftyp'
unsigned char end_marker[] = { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79 }; // 'Xtra'
int file_count = 0;
long current_pos = 0;
FILE *input_fh = fopen(input_filename, "rb");
if (!input_fh) {
perror("Cannot open input file");
return EXIT_FAILURE;
}
char basename[256];
get_basename_without_extension(input_filename, basename);
while (1) {
// Find the start marker (e.g., 'ftyp')
long start = find_marker(input_fh, start_marker, sizeof(start_marker));
if (start == -1) {
break;
}
// Find the end marker ('Xtra')
long end = find_marker(input_fh, end_marker, sizeof(end_marker));
if (end == -1) {
// If the end marker is not found, use the end of the file
fseek(input_fh, 0, SEEK_END);
end = ftell(input_fh);
}
// Calculate the size of the segment to extract
long segment_size = end - start;
// Create an output filename with the start position and segment size in hexadecimal
char output_filename[512];
snprintf(output_filename, sizeof(output_filename), "%s_%.8lx_%.8lx.mp4", basename, start, segment_size);
// Extract the MP4 segment
extract_mp4(input_filename, start, end, output_filename);
printf("Extracted: %s\n", output_filename);
file_count++;
// Update the position for the next marker search
fseek(input_fh, end, SEEK_SET);
}
fclose(input_fh);
printf("Total MP4 files extracted: %d\n", file_count);
return EXIT_SUCCESS;
}