Credit Andrew R for finding the direct copy mods for exr and ppm sequences
[goodguy/cinelerra.git] / cinelerra-5.1 / libzmpeg3 / mpeg3split.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "mpeg3private.inc"
6
7 void copy_data(FILE *out, FILE *in, long bytes)
8 {
9         long fragment_size = 0x100000;
10         char *buffer = malloc(fragment_size);
11         long i;
12         
13         for(i = 0; i < bytes; i += fragment_size)
14         {
15                 if(i + fragment_size > bytes) fragment_size = bytes - i;
16                 if(!fread(buffer, 1, fragment_size, in))
17                 {
18                         perror("copy_data");
19                 }
20                 if(!fwrite(buffer, 1, fragment_size, out))
21                 {
22                         perror("copy_data");
23                 }
24         }
25         
26         free(buffer);
27 }
28
29 void split_video(char *path, long default_fragment_size)
30 {
31         long current_byte = 0;
32         int result = 0;
33         int i = 0;
34         long total_bytes;
35         FILE *in = fopen(path, "r");
36         char *sequence_hdr;
37         long sequence_hdr_size;
38         unsigned long header = 0;
39         long header_start;
40         long header_end;
41
42         if(!in)
43         {
44                 perror("split_file");
45                 return;
46         }
47         fseek(in, 0, SEEK_END);
48         total_bytes = ftell(in);
49         fseek(in, 0, SEEK_SET);
50
51 // Copy sequence header
52         do{
53                 header <<= 8;
54                 header = (header & 0xffffffff) | getc(in);
55         }while(header != MPEG3_SEQUENCE_START_CODE && !feof(in));
56
57         header_start = ftell(in) - 4;
58         do{
59                 header <<= 8;
60                 header = (header & 0xffffffff) | getc(in);
61         }while(header != MPEG3_GOP_START_CODE && !feof(in));
62         header_end = ftell(in) - 4;
63
64         sequence_hdr_size = header_end - header_start;
65         sequence_hdr = malloc(sequence_hdr_size);
66         fseek(in, header_start, SEEK_SET);
67         fread(sequence_hdr, 1, sequence_hdr_size, in);
68         fseek(in, 0, SEEK_SET);
69
70         while(current_byte < total_bytes && !result)
71         {
72                 FILE *out;
73                 char outpath[1024];
74                 long fragment_size;
75
76                 sprintf(outpath, "%s%02d", path, i);
77                 out = fopen(outpath, "w");
78                 if(!out)
79                 {
80                         perror("split_file");
81                         break;
82                 }
83
84 // Default fragment size
85                 fragment_size = default_fragment_size;
86 // Corrected fragment size
87                 if(current_byte + fragment_size >= total_bytes)
88                 {
89                         fragment_size = total_bytes - current_byte;
90                 }
91                 else
92                 {
93                         header = 0;
94
95 // Get GOP header
96                         fseek(in, current_byte + fragment_size, SEEK_SET);
97                         do
98                         {
99                                 fseek(in, -1, SEEK_CUR);
100                                 header >>= 8;
101                                 header |= ((unsigned long)fgetc(in)) << 24;
102                                 fseek(in, -1, SEEK_CUR);
103                         }while(ftell(in) > 0 && header != MPEG3_GOP_START_CODE);
104                         fragment_size = ftell(in) - current_byte;
105                         fseek(in, current_byte, SEEK_SET);
106                 }
107
108 // Put sequence header
109                 if(current_byte > 0)
110                 {
111                         fwrite(sequence_hdr, 1, sequence_hdr_size, out);
112                 }
113
114 // Put data
115                 copy_data(out, in, fragment_size);
116
117                 fclose(out);
118                 i++;
119                 current_byte += fragment_size; 
120         }
121         free(sequence_hdr);
122 }
123
124 int main(int argc, char *argv[])
125 {
126         long bytes = 0;
127         int i;
128         
129         if(argc < 2)
130         {
131                 fprintf(stderr, "Split elementary streams into chunks of bytes.\n"
132                         "Usage: mpeg3split -b bytes <infile>\n");
133                 exit(1);
134         }
135         
136         for(i = 1; i < argc; i++)
137         {
138                 if(!strcmp(argv[i], "-b"))
139                 {
140                         if(i < argc - 1)
141                         {
142                                 i++;
143                                 bytes = atol(argv[i]);
144                         }
145                         else
146                         {
147                                 fprintf(stderr, "-b must be paired with a value\n");
148                                 exit(1);
149                         }
150                 }
151                 else
152                 if(bytes > 0)
153                 {
154 // Split a file
155                         split_video(argv[i], bytes);
156                 }
157                 else
158                 {
159                         fprintf(stderr, "No value for bytes specified,\n");
160                         exit(1);
161                 }
162         }
163 }
164
165