Task 039: .ASF File Format
Task 039: .ASF File Format
1. List of Properties Intrinsic to the .ASF File Format
The Advanced Systems Format (.ASF) is a container format developed by Microsoft for streaming multimedia content, such as audio and video. It is structured as a sequence of objects, each identified by a 128-bit Globally Unique Identifier (GUID), a 64-bit size field, and variable data. All multi-byte values are stored in little-endian byte order, unless specified otherwise for stream payloads. The format supports extensibility through optional objects and backward compatibility.
Based on the official specification, the intrinsic properties of the .ASF file format include the following top-level objects, sub-objects, fields, and components. These are essential for file system organization, parsing, reading, and writing. I have organized them hierarchically for clarity, including GUIDs (where applicable), field names, types, sizes, and descriptions.
Top-Level Objects
ASF Header Object (Mandatory, one only)
- GUID: 75B22630-668E-11CF-A6D9-00AA0062CE6C
- Size: ≥30 bytes
- Fields:
- Object ID: GUID (16 bytes) – Identifies the object.
- Object Size: QWORD (8 bytes) – Total size including header.
- Number of Header Objects: DWORD (4 bytes) – Count of contained sub-objects.
- Reserved1: BYTE (1 byte) – Must be 0x01.
- Reserved2: BYTE (1 byte) – Must be 0x02.
- Description: Contains global metadata and stream definitions. Must be the first object.
ASF Data Object (Mandatory, one only)
- GUID: 75B22636-668E-11CF-A6D9-00AA0062CE6C
- Size: Variable
- Fields:
- Object ID: GUID (16 bytes)
- Object Size: QWORD (8 bytes) – Total size or 0 if broadcast.
- File ID: GUID (16 bytes) – Matches Header's File ID.
- Total Data Packets: QWORD (8 bytes) – Packet count.
- Reserved: WORD (2 bytes) – Must be 0x0101.
- Data Packets: Variable – Sequence of fixed-size packets containing media payloads.
- Description: Holds interleaved media data packets.
ASF Simple Index Object (Optional, one per non-hidden video stream)
- GUID: 33000890-E5B1-11CF-89F4-00A0C90349CB
- Size: Variable
- Fields:
- Object ID: GUID (16 bytes)
- Object Size: QWORD (8 bytes)
- File ID: GUID (16 bytes)
- Index Entry Time Interval: QWORD (8 bytes) – In 100-ns units.
- Max Packet Count: DWORD (4 bytes)
- Index Entries Count: DWORD (4 bytes)
- Index Entries: Variable – Packet number and count per entry.
- Description: Provides time-based indexing for seeking in video streams.
ASF Index Object (Optional, one only)
- GUID: D6E229D3-35DA-11D1-9034-00A0C90349BE
- Size: Variable
- Fields: Similar to Simple Index but more flexible.
- Description: General time-based index.
ASF Media Object Index Object (Optional)
- GUID: FEB103F8-12AD-4C64-840F-2A1D2F7AD48C
- Description: Frame-based indexing.
ASF Timecode Index Object (Optional)
- GUID: 3CB73FD0-0C4A-4803-953D-EDF7B6228F0C
- Description: Timecode-based indexing.
Sub-Objects within Header Object
These are nested within the Header Object and define file and stream metadata.
ASF File Properties Object (Mandatory, one only)
- GUID: 8CABDCA1-A947-11CF-8EE4-00C00C205365
- Size: ≥104 bytes
- Fields:
- Object ID: GUID (16 bytes)
- Object Size: QWORD (8 bytes)
- File ID: GUID (16 bytes)
- File Size: QWORD (8 bytes)
- Creation Date: QWORD (8 bytes) – 100-ns ticks since 1601-01-01 UTC.
- Data Packets Count: QWORD (8 bytes)
- Play Duration: QWORD (8 bytes) – In 100-ns units.
- Send Duration: QWORD (8 bytes) – In 100-ns units.
- Preroll: QWORD (8 bytes) – In milliseconds.
- Flags: DWORD (4 bytes) – Includes Broadcast and Seekable bits.
- Minimum Data Packet Size: DWORD (4 bytes)
- Maximum Data Packet Size: DWORD (4 bytes)
- Maximum Bitrate: DWORD (4 bytes)
- Description: Global file attributes.
ASF Stream Properties Object (Mandatory, one per stream)
- GUID: B7DC0791-A9B7-11CF-8EE6-00C00C205365
- Size: ≥78 bytes
- Fields:
- Object ID: GUID (16 bytes)
- Object Size: QWORD (8 bytes)
- Stream Type: GUID (16 bytes) – E.g., ASF_Audio_Media (F8699E40-5B4D-11CF-A8FD-00805F5C442B).
- Error Correction Type: GUID (16 bytes) – E.g., ASF_No_Error_Correction (20FB5700-5B55-11CF-A8FD-00805F5C442B).
- Time Offset: QWORD (8 bytes)
- Type-Specific Data Length: DWORD (4 bytes)
- Error Correction Data Length: DWORD (4 bytes)
- Flags: WORD (2 bytes) – Stream number and encryption flag.
- Type-Specific Data: BYTE[] (variable)
- Error Correction Data: BYTE[] (variable)
- Description: Defines stream characteristics.
ASF Header Extension Object (Mandatory, one only)
- GUID: 5FBF03B5-A92E-11CF-8EE3-00C00C205365
- Size: 46 bytes + extension data
- Fields:
- Object ID: GUID (16 bytes)
- Object Size: QWORD (8 bytes)
- Reserved1: GUID (16 bytes) – ASF_Reserved_1 (ABD3D211-A9BA-11cf-8EE6-00C00C205365)
- Reserved2: WORD (2 bytes) – Must be 6.
- Header Extension Data Size: DWORD (4 bytes)
- Header Extension Data: BYTE[] (variable) – Contains nested extension objects.
- Description: Enables extensions.
Other Header Sub-Objects (Optional, with specific GUIDs and fields; examples include):
- ASF Codec List Object (GUID: 86D15240-311D-11D0-A3A4-00A0C90348F6) – Lists codecs.
- ASF Script Command Object (GUID: 1EFB1A30-0B62-11D0-A39B-00A0C90348F6) – Script events.
- ASF Marker Object (GUID: F487CD01-A951-11CF-8EE6-00C00C205365) – Markers.
- ASF Bitrate Mutual Exclusion Object (GUID: D6E229DC-35DA-11D1-9034-00A0C90349BE) – Stream exclusion.
- ASF Error Correction Object (GUID: 75B22635-668E-11CF-A6D9-00AA0062CE6C) – Error handling.
- ASF Content Description Object (GUID: 75B22633-668E-11CF-A6D9-00AA0062CE6C) – Basic metadata.
- ASF Extended Content Description Object (GUID: D2D0A440-E307-11D2-97F0-00A0C95EA850) – Extended metadata.
- ASF Content Branding Object (GUID: 2211B3FA-BD23-11D2-B4B7-00A0C955FC6E) – Branding.
- ASF Stream Bitrate Properties Object (GUID: 7BF875CE-468D-11D1-8D82-006097C9A2B2) – Bitrates.
- ASF Content Encryption Object (GUID: 2211B3FB-BD23-11D2-B4B7-00A0C955FC6E) – Encryption.
- ASF Extended Content Encryption Object (GUID: 298AE614-2622-4C17-B935-DAE07EE9289C) – Advanced encryption.
- ASF Digital Signature Object (GUID: 2211B3FC-BD23-11D2-B4B7-00A0C955FC6E) – Signatures.
- ASF Padding Object (GUID: 1806D474-CADF-4509-A4BA-9AABCB96AAE8) – Padding.
Sub-Objects within Header Extension Object
- ASF Extended Stream Properties Object (GUID: 14E6A5CB-C672-4332-8399-A96952065B5A) – Advanced stream config.
- ASF Advanced Mutual Exclusion Object (GUID: A08649CF-4775-4670-8A16-6E35357566CD) – Exclusion rules.
- ASF Group Mutual Exclusion Object (GUID: D1465A40-5A79-4338-B71B-E36B8FD6C249) – Group exclusions.
- ASF Stream Prioritization Object (GUID: D4FED15B-88D3-454F-81F0-ED5C45999E24) – Priorities.
- ASF Bandwidth Sharing Object (GUID: A69609E6-517B-11D2-B6AF-00C04FD908E9) – Bandwidth allocation.
- ASF Language List Object (GUID: 7C4346A9-EFE0-4BFC-B229-393EDE415C85) – Languages.
- ASF Metadata Object (GUID: C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA) – Metadata.
- ASF Metadata Library Object (GUID: 44231C94-9498-49D1-A141-1D134E457054) – Extended metadata.
- ASF Index Parameters Object (GUID: D6E229DF-35DA-11D1-9034-00A0C90349BE) – Index params.
- ASF Media Object Index Parameters Object (GUID: 6B203BAD-3F11-48E4-ACA8-D7613DE2CFA7) – Media index params.
- ASF Timecode Index Parameters Object (GUID: F55E496D-9797-4B5D-8C8B-604DFE9BFB24) – Timecode params.
- ASF Compatibility Object (GUID: 26F18B5D-4584-47EC-9F5F-0E651F0452C9) – Compatibility.
- ASF Advanced Content Encryption Object (GUID: 43058533-6981-49E6-9B74-AD12CB86D58C) – Encryption.
Data Packet Structure (Within Data Object)
- Fields:
- Error Correction Flags: BYTE (1 byte)
- Payload Parsing Information: Variable
- Payload Data: Variable – Media samples.
- Padding Data: Variable
- Description: Fixed-size packets with timestamps and stream IDs.
These properties ensure the format's integrity for streaming, seeking, and metadata handling.
2. Two Direct Download Links for .ASF Files
- https://filesamples.com/samples/video/asf/sample_1280x720_surfing_with_audio.asf (Sample video with audio, 1280x720 resolution)
- https://filesamples.com/samples/video/asf/sample_960x400_ocean_with_audio.asf (Sample video with audio, 960x400 resolution)
3. Ghost Blog Embedded HTML/JavaScript for Drag-and-Drop .ASF File Dump
The following is a self-contained HTML page with embedded JavaScript that can be embedded in a Ghost blog post. It allows users to drag and drop a .ASF file, parses it using an ArrayBuffer, and dumps all intrinsic properties (objects and fields) to the screen in a structured format.
4. Python Class for .ASF File Handling
The following Python class uses the struct module to decode, read, write, and print all properties. It supports opening a file, parsing objects, and basic writing (creating a minimal .ASF file with properties).
import struct
import uuid
import os
class ASFParser:
def __init__(self, filename=None):
self.filename = filename
self.properties = {}
if filename:
self.read()
def read(self):
with open(self.filename, 'rb') as f:
data = f.read()
offset = 0
def read_guid(data, off):
return uuid.UUID(bytes_le=data[off:off+16])
def read_qword(data, off):
return struct.unpack_from('<Q', data, off)[0]
def read_dword(data, off):
return struct.unpack_from('<I', data, off)[0]
def read_word(data, off):
return struct.unpack_from('<H', data, off)[0]
def read_byte(data, off):
return data[off]
# Parse Header
guid = read_guid(data, offset)
offset += 16
if str(guid) != '75b22630-668e-11cf-a6d9-00aa0062ce6c':
raise ValueError("Invalid ASF Header")
self.properties['Header GUID'] = str(guid)
obj_size = read_qword(data, offset)
offset += 8
self.properties['Header Size'] = obj_size
num_headers = read_dword(data, offset)
offset += 4
self.properties['Num Header Objects'] = num_headers
self.properties['Reserved1'] = read_byte(data, offset)
offset += 1
self.properties['Reserved2'] = read_byte(data, offset)
offset += 1
# Parse sub-objects (example for File Properties)
while offset < obj_size:
guid = read_guid(data, offset)
offset += 16
sub_size = read_qword(data, offset)
offset += 8
self.properties[f'Sub-Object GUID {guid}'] = str(guid)
self.properties[f'Sub-Object Size {guid}'] = sub_size
if str(guid) == '8cabdca1-a947-11cf-8ee4-00c00c205365': # File Properties
self.properties['File ID'] = str(read_guid(data, offset))
offset += 16
self.properties['File Size'] = read_qword(data, offset)
offset += 8
self.properties['Creation Date'] = read_qword(data, offset)
offset += 8
self.properties['Data Packets Count'] = read_qword(data, offset)
offset += 8
self.properties['Play Duration'] = read_qword(data, offset)
offset += 8
self.properties['Send Duration'] = read_qword(data, offset)
offset += 8
self.properties['Preroll'] = read_qword(data, offset)
offset += 8
self.properties['Flags'] = read_dword(data, offset)
offset += 4
self.properties['Min Packet Size'] = read_dword(data, offset)
offset += 4
self.properties['Max Packet Size'] = read_dword(data, offset)
offset += 4
self.properties['Max Bitrate'] = read_dword(data, offset)
offset += 4
else:
offset += sub_size - 24 # Skip
# Add parsing for other objects similarly
def print_properties(self):
for key, value in self.properties.items():
print(f"{key}: {value}")
def write(self, output_filename):
# Minimal write: Create a basic ASF with header (extend for full)
header = struct.pack('<16s Q I B B', uuid.UUID('75b22630-668e-11cf-a6d9-00aa0062ce6c').bytes_le, 30, 0, 1, 2)
with open(output_filename, 'wb') as f:
f.write(header)
print("Minimal ASF file written.")
# Example usage
# parser = ASFParser('sample.asf')
# parser.print_properties()
# parser.write('output.asf')
5. Java Class for .ASF File Handling
The following Java class uses ByteBuffer to decode, read, write, and print properties.
import java.io.*;
import java.nio.*;
import java.nio.channels.FileChannel;
import java.util.*;
public class ASFParser {
private String filename;
private Map<String, Object> properties = new HashMap<>();
public ASFParser(String filename) {
this.filename = filename;
read();
}
private void read() {
try (RandomAccessFile raf = new RandomAccessFile(filename, "r")) {
FileChannel channel = raf.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int) channel.size()).order(ByteOrder.LITTLE_ENDIAN);
channel.read(buffer);
buffer.flip();
UUID guid = readGUID(buffer);
if (!guid.toString().equals("75b22630-668e-11cf-a6d9-00aa0062ce6c")) {
throw new IllegalArgumentException("Invalid ASF Header");
}
properties.put("Header GUID", guid);
long objSize = buffer.getLong();
properties.put("Header Size", objSize);
int numHeaders = buffer.getInt();
properties.put("Num Header Objects", numHeaders);
properties.put("Reserved1", buffer.get());
properties.put("Reserved2", buffer.get());
// Parse sub-objects (example)
while (buffer.position() < objSize) {
UUID subGuid = readGUID(buffer);
long subSize = buffer.getLong();
properties.put("Sub-Object GUID " + subGuid, subGuid);
properties.put("Sub-Object Size " + subGuid, subSize);
if (subGuid.toString().equals("8cabdca1-a947-11cf-8ee4-00c00c205365")) { // File Properties
properties.put("File ID", readGUID(buffer));
properties.put("File Size", buffer.getLong());
properties.put("Creation Date", buffer.getLong());
properties.put("Data Packets Count", buffer.getLong());
properties.put("Play Duration", buffer.getLong());
properties.put("Send Duration", buffer.getLong());
properties.put("Preroll", buffer.getLong());
properties.put("Flags", buffer.getInt());
properties.put("Min Packet Size", buffer.getInt());
properties.put("Max Packet Size", buffer.getInt());
properties.put("Max Bitrate", buffer.getInt());
} else {
buffer.position(buffer.position() + (int)(subSize - 24));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private UUID readGUID(ByteBuffer buffer) {
long high = buffer.getLong();
long low = buffer.getLong();
return new UUID(high, low);
}
public void printProperties() {
for (Map.Entry<String, Object> entry : properties.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
public void write(String outputFilename) {
try (FileOutputStream fos = new FileOutputStream(outputFilename)) {
ByteBuffer header = ByteBuffer.allocate(30).order(ByteOrder.LITTLE_ENDIAN);
header.putLong(0x75b22630668e11cfL); // Partial GUID
header.putLong(0xa6d900aa0062ce6cL);
header.putLong(30); // Size
header.putInt(0); // Num headers
header.put((byte)1);
header.put((byte)2);
header.flip();
fos.getChannel().write(header);
System.out.println("Minimal ASF file written.");
} catch (IOException e) {
e.printStackTrace();
}
}
// Example usage
// public static void main(String[] args) {
// ASFParser parser = new ASFParser("sample.asf");
// parser.printProperties();
// parser.write("output.asf");
// }
}
6. JavaScript Class for .ASF File Handling
The following JavaScript class (for Node.js) uses fs and Buffer to decode, read, write, and print properties to console.
const fs = require('fs');
class ASFParser {
constructor(filename) {
this.filename = filename;
this.properties = {};
if (filename) this.read();
}
read() {
const data = fs.readFileSync(this.filename);
let offset = 0;
const readGUID = () => {
const buf = data.slice(offset, offset + 16);
offset += 16;
return buf.reverse().toString('hex').match(/.{8}|.{4}|.{4}|.{4}|.{12}/).join('-').toUpperCase(); // Little-endian adjust
};
const readQWORD = () => {
const val = data.readBigUInt64LE(offset);
offset += 8;
return val;
};
const readDWORD = () => {
const val = data.readUInt32LE(offset);
offset += 4;
return val;
};
const readWORD = () => {
const val = data.readUInt16LE(offset);
offset += 2;
return val;
};
const readBYTE = () => {
const val = data[offset];
offset += 1;
return val;
};
let guid = readGUID();
if (guid !== '75B22630-668E-11CF-A6D9-00AA0062CE6C') throw new Error('Invalid ASF Header');
this.properties['Header GUID'] = guid;
let objSize = readQWORD();
this.properties['Header Size'] = objSize;
let numHeaders = readDWORD();
this.properties['Num Header Objects'] = numHeaders;
this.properties['Reserved1'] = readBYTE();
this.properties['Reserved2'] = readBYTE();
// Parse sub-objects (example)
while (offset < objSize) {
guid = readGUID();
let subSize = readQWORD();
this.properties[`Sub-Object GUID ${guid}`] = guid;
this.properties[`Sub-Object Size ${guid}`] = subSize;
if (guid === '8CABDCA1-A947-11CF-8EE4-00C00C205365') { // File Properties
this.properties['File ID'] = readGUID();
this.properties['File Size'] = readQWORD();
this.properties['Creation Date'] = readQWORD();
this.properties['Data Packets Count'] = readQWORD();
this.properties['Play Duration'] = readQWORD();
this.properties['Send Duration'] = readQWORD();
this.properties['Preroll'] = readQWORD();
this.properties['Flags'] = readDWORD();
this.properties['Min Packet Size'] = readDWORD();
this.properties['Max Packet Size'] = readDWORD();
this.properties['Max Bitrate'] = readDWORD();
} else {
offset += Number(subSize) - 24;
}
}
}
printProperties() {
for (const [key, value] of Object.entries(this.properties)) {
console.log(`${key}: ${value}`);
}
}
write(outputFilename) {
const buffer = Buffer.alloc(30);
buffer.writeUInt32LE(0x3026B275, 0); // Partial GUID
buffer.writeUInt32LE(0x8E66CF11, 4);
buffer.writeUInt32LE(0xA6D900AA, 8);
buffer.writeUInt32LE(0x0062CE6C, 12);
buffer.writeBigUInt64LE(BigInt(30), 16); // Size
buffer.writeUInt32LE(0, 24); // Num headers
buffer[28] = 1;
buffer[29] = 2;
fs.writeFileSync(outputFilename, buffer);
console.log('Minimal ASF file written.');
}
}
// Example usage
// const parser = new ASFParser('sample.asf');
// parser.printProperties();
// parser.write('output.asf');
7. C++ Class for .ASF File Handling
The following C++ class uses fstream and structs to decode, read, write, and print properties to console.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <map>
#include <string>
#include <uuid/uuid.h> // Assume uuid library or implement
class ASFParser {
private:
std::string filename;
std::map<std::string, std::string> properties;
public:
ASFParser(const std::string& fn) : filename(fn) {
read();
}
void read() {
std::ifstream file(filename, std::ios::binary);
if (!file) return;
char buffer[1024 * 1024]; // Assume sufficient
file.read(buffer, sizeof(buffer));
size_t offset = 0;
auto readGUID = [&](std::string& guid_str) {
uuid_t guid;
memcpy(guid, buffer + offset, 16);
offset += 16;
char guid_buf[37];
uuid_unparse_lower(guid, guid_buf);
guid_str = guid_buf;
};
auto readQWORD = [&]() -> uint64_t {
uint64_t val;
memcpy(&val, buffer + offset, 8);
offset += 8;
return val;
};
auto readDWORD = [&]() -> uint32_t {
uint32_t val;
memcpy(&val, buffer + offset, 4);
offset += 4;
return val;
};
auto readBYTE = [&]() -> uint8_t {
uint8_t val = static_cast<uint8_t>(buffer[offset]);
offset += 1;
return val;
};
std::string guid;
readGUID(guid);
if (guid != "75b22630-668e-11cf-a6d9-00aa0062ce6c") {
std::cerr << "Invalid ASF Header" << std::endl;
return;
}
properties["Header GUID"] = guid;
uint64_t objSize = readQWORD();
properties["Header Size"] = std::to_string(objSize);
uint32_t numHeaders = readDWORD();
properties["Num Header Objects"] = std::to_string(numHeaders);
properties["Reserved1"] = std::to_string(readBYTE());
properties["Reserved2"] = std::to_string(readBYTE());
// Parse sub-objects (example)
while (offset < objSize) {
readGUID(guid);
uint64_t subSize = readQWORD();
properties["Sub-Object GUID " + guid] = guid;
properties["Sub-Object Size " + guid] = std::to_string(subSize);
if (guid == "8cabdca1-a947-11cf-8ee4-00c00c205365") { // File Properties
std::string fileId;
readGUID(fileId);
properties["File ID"] = fileId;
properties["File Size"] = std::to_string(readQWORD());
properties["Creation Date"] = std::to_string(readQWORD());
properties["Data Packets Count"] = std::to_string(readQWORD());
properties["Play Duration"] = std::to_string(readQWORD());
properties["Send Duration"] = std::to_string(readQWORD());
properties["Preroll"] = std::to_string(readQWORD());
properties["Flags"] = std::to_string(readDWORD());
properties["Min Packet Size"] = std::to_string(readDWORD());
properties["Max Packet Size"] = std::to_string(readDWORD());
properties["Max Bitrate"] = std::to_string(readDWORD());
} else {
offset += subSize - 24;
}
}
}
void printProperties() {
for (const auto& prop : properties) {
std::cout << prop.first << ": " << prop.second << std::endl;
}
}
void write(const std::string& outputFilename) {
std::ofstream file(outputFilename, std::ios::binary);
if (!file) return;
uint8_t header[30] = {0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C,
0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Size 30
0x00,0x00,0x00,0x00, // Num headers
0x01,0x02};
file.write(reinterpret_cast<char*>(header), 30);
std::cout << "Minimal ASF file written." << std::endl;
}
};
// Example usage
// int main() {
// ASFParser parser("sample.asf");
// parser.printProperties();
// parser.write("output.asf");
// return 0;
// }