2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License along
13 * with this program; if not, write to the Free Software Foundation, Inc.,
14 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // simple ASF header display program by A'rpi/ESP-team
20 // .asf fileformat docs from http://divx.euro.ru
25 typedef struct __attribute__((packed
))
27 long biSize
; // sizeof(BITMAPINFOHEADER)
30 short biPlanes
; // unused
32 long biCompression
; // fourcc of image
33 long biSizeImage
; // size of image. For uncompressed images
34 // ( biCompression 0 or 3 ) can be zero.
37 long biXPelsPerMeter
; // unused
38 long biYPelsPerMeter
; // unused
39 long biClrUsed
; // valid only for palettized images.
40 // Number of colors in palette.
46 short wFormatTag
; // value that identifies compression format
50 short nBlockAlign
; // size of a data sample
52 short cbSize
; // size of format-specific data
55 typedef struct __attribute__((packed
)) {
56 unsigned char guid
[16];
57 unsigned long long size
;
60 typedef struct __attribute__((packed
)) {
61 ASF_obj_header_t objh
;
62 unsigned int cno
; // number of subchunks
63 unsigned char v1
; // unknown (0x01)
64 unsigned char v2
; // unknown (0x02)
67 typedef struct __attribute__((packed
)) {
68 unsigned char client
[16]; // Client GUID
69 unsigned long long file_size
;
70 unsigned long long creat_time
; //File creation time FILETIME 8
71 unsigned long long packets
; //Number of packets UINT64 8
72 unsigned long long end_timestamp
; //Timestamp of the end position UINT64 8
73 unsigned long long duration
; //Duration of the playback UINT64 8
74 unsigned long start_timestamp
; //Timestamp of the start position UINT32 4
75 unsigned long unk1
; //Unknown, maybe reserved ( usually contains 0 ) UINT32 4
76 unsigned long flags
; //Unknown, maybe flags ( usually contains 2 ) UINT32 4
77 unsigned long packetsize
; //Size of packet, in bytes UINT32 4
78 unsigned long packetsize2
; //Size of packet ( confirm ) UINT32 4
79 unsigned long frame_size
; //Size of uncompressed video frame UINT32 4
82 typedef struct __attribute__((packed
)) {
83 unsigned char type
[16]; // Stream type (audio/video) GUID 16
84 unsigned char concealment
[16]; // Audio error concealment type GUID 16
85 unsigned long long unk1
; // Unknown, maybe reserved ( usually contains 0 ) UINT64 8
86 unsigned long type_size
; //Total size of type-specific data UINT32 4
87 unsigned long stream_size
; //Size of stream-specific data UINT32 4
88 unsigned short stream_no
; //Stream number UINT16 2
89 unsigned long unk2
; //Unknown UINT32 4
90 } ASF_stream_header_t
;
92 typedef struct __attribute__((packed
)) {
93 unsigned char streamno
;
101 ASF_obj_header_t objh
;
102 ASF_file_header_t fileh
;
103 ASF_stream_header_t streamh
;
104 unsigned char buffer
[8192];
108 static char* chunk_type(unsigned char* guid
){
109 switch(*((unsigned int*)guid
)){
110 case 0xF8699E40: return "guid_audio_stream";
111 case 0xBC19EFC0: return "guid_video_stream";
112 case 0x49f1a440: return "guid_audio_conceal_none";
113 case 0xbfc3cd50: return "guid_audio_conceal_interleave";
114 case 0x75B22630: return "guid_header";
115 case 0x75b22636: return "guid_data_chunk";
116 case 0x33000890: return "guid_index_chunk";
117 case 0xB7DC0791: return "guid_stream_header";
118 case 0xD6E229D1: return "guid_header_2_0";
119 case 0x8CABDCA1: return "guid_file_header";
124 static void print_wave_header(WAVEFORMATEX
*h
){
125 printf("======= WAVE Format =======\n");
127 printf("Format Tag: %d (0x%X)\n", h
->wFormatTag
, h
->wFormatTag
);
128 printf("Channels: %d\n", h
->nChannels
);
129 printf("Samplerate: %ld\n", h
->nSamplesPerSec
);
130 printf("avg byte/sec: %ld\n", h
->nAvgBytesPerSec
);
131 printf("Block align: %d\n", h
->nBlockAlign
);
132 printf("bits/sample: %d\n", h
->wBitsPerSample
);
133 printf("cbSize: %d\n", h
->cbSize
);
135 switch(h
->wFormatTag
){
136 case 0x01: printf("Audio in PCM format\n"); break;
137 case 0x50: printf("Audio in MPEG Layer 1/2 format\n"); break;
138 case 0x55: printf("Audio in MPEG Layer-3 format\n"); break; // ACM
139 case 0x02: printf("Audio in MS ADPCM format\n"); break; // ACM
140 case 0x11: printf("Audio in IMA ADPCM format\n"); break; // ACM
142 case 0x32: printf("Audio in MS GSM 6.10 format\n"); break; // ACM
144 case 0x161: printf("Audio in DivX WMA format\n"); break; // ACM
145 default: printf("Audio in UNKNOWN (id=0x%X) format\n", h
->wFormatTag
);
148 printf("===========================\n");
151 static void print_video_header(BITMAPINFOHEADER
*h
){
152 printf("======= VIDEO Format ======\n");
153 printf(" biSize %ld\n", h
->biSize
);
154 printf(" biWidth %ld\n", h
->biWidth
);
155 printf(" biHeight %ld\n", h
->biHeight
);
156 printf(" biPlanes %d\n", h
->biPlanes
);
157 printf(" biBitCount %d\n", h
->biBitCount
);
158 printf(" biCompression %ld='%.4s'\n", h
->biCompression
, (const char*)&h
->biCompression
);
159 printf(" biSizeImage %ld\n", h
->biSizeImage
);
160 printf("===========================\n");
165 int main(int argc
, char* argv
[]){
166 FILE *f
= fopen(argc
> 1 ? argv
[1] : "Alice Deejay - Back In My Life.asf", "rb");
169 printf("file not found\n");
173 //printf("sizeof=%d\n", sizeof(objh));
174 //printf("sizeof=%d\n", sizeof(asfh));
176 fread(&asfh
, sizeof(asfh
), 1, f
); // header obj
177 //for(i = 0; i < 16; i++)
178 // printf("%02X ", asfh.objh.guid[i]);
179 printf("[%s] %d (subchunks: %d)\n", chunk_type(asfh
.objh
.guid
),
180 (int) asfh
.objh
.size
, asfh
.cno
);
182 while(fread(&objh
, sizeof(objh
), 1, f
) > 0){
184 //for(i = 0; i < 16; i++)
185 // printf("%02X ", objh.guid[i]);
186 printf("0x%08X [%s] %d\n", pos
-sizeof(objh
), chunk_type(objh
.guid
),
188 switch(*((unsigned int*)&objh
.guid
)){
189 case 0xB7DC0791: // guid_stream_header
190 fread(&streamh
, sizeof(streamh
), 1, f
);
191 printf("stream type: %s\n", chunk_type(streamh
.type
));
192 printf("stream concealment: %s\n", chunk_type(streamh
.concealment
));
193 printf("type: %d bytes, stream: %d bytes ID: %d\n",
194 (int)streamh
.type_size
, (int)streamh
.stream_size
,
195 (int)streamh
.stream_no
);
196 printf("FILEPOS=0x%lX\n", ftell(f
));
197 // type-specific data:
198 fread(buffer
,streamh
.type_size
,1,f
);
199 switch(*((unsigned int*)&streamh
.type
)){
200 case 0xF8699E40: // guid_audio_stream
201 print_wave_header((WAVEFORMATEX
*)buffer
);
203 case 0xBC19EFC0: // guid_video_stream
204 print_video_header((BITMAPINFOHEADER
*)&buffer
[4 + 4 + 1 + 2]);
207 // stream-specific data:
208 fread(buffer
, streamh
.stream_size
, 1, f
);
211 // return "guid_header_2_0";
212 case 0x8CABDCA1: // guid_file_header
213 fread(&fileh
, sizeof(fileh
), 1, f
);
214 printf("packets: %d flags: %d pack_size: %d frame_size: %d\n",
215 (int)fileh
.packets
, (int)fileh
.flags
, (int)fileh
.packetsize
,
216 (int)fileh
.frame_size
);
218 case 0x75b22636: // guid_data_chunk
219 { int endp
= pos
+ objh
.size
- sizeof(objh
);
220 unsigned char* packet
= malloc((int)fileh
.packetsize
);
222 fseek(f
, 26, SEEK_CUR
);
223 while((fpos
= ftell(f
)) < endp
){
224 fread(packet
, (int)fileh
.packetsize
, 1, f
);
225 if(packet
[0] == 0x82){
226 unsigned char flags
= packet
[3];
227 unsigned char* p
= &packet
[5];
229 unsigned short duration
;
238 padding
= p
[0] | (p
[1] << 8);
241 time
= *((unsigned long*)p
);
243 duration
= *((unsigned short*)p
);
249 printf("%08X: flag=%02X segs=%d pad=%d time=%ld dur=%d\n",
250 fpos
, flags
, segs
, padding
, time
, duration
);
251 for(seg
= 0; seg
< segs
; seg
++){
252 ASF_segmhdr_t
* sh
= (ASF_segmhdr_t
*)p
;
254 p
+= sizeof(ASF_segmhdr_t
);
255 if(sh
->flag
& 8) p
+=8;// else
256 if(sh
->flag
& 1) ++p
;
258 len
= *((unsigned short*)p
);
261 printf(" seg #%d: streamno=%d seq=%d flag=%02X len=%d\n",
262 seg
, sh
->streamno
&0x7F, sh
->seq
, sh
->flag
, len
);
264 if(!streams
[sh
->streamno
& 0x7F]){
266 snprintf(name
, 256, "stream%02X.dat", sh
->streamno
& 0x7F);
267 streams
[sh
->streamno
& 0x7F] = fopen(name
, "wb");
269 fwrite(p
, len
, 1, streams
[sh
->streamno
& 0x7F]);
274 printf("%08X: UNKNOWN %02X %02X %02X %02X %02X...\n", fpos
,
275 packet
[0], packet
[1], packet
[2], packet
[3], packet
[4]);
281 // return "guid_index_chunk";
284 fseek(f
, pos
+ objh
.size
- sizeof(objh
), SEEK_SET
);