HomeForumSourceResearchGuide
Sign in to contribute to source. how it works
Component media.video.VideoFile:divf by barry
expand copy to clipboardexpand
data Header {
	byte signature[4]
	int2 version
	int2 headerLength
	byte fourcc[4]
	int2 width
	int2 height
	int4 numerator
	int4 denominator
	int4 frameCount
	int4 unused
}

data FrameHeader {
	int4 frameSize
	int8 timestamp
}

data Int2 {
	int2 value
}

data Int4 {
	int4 value
}

const byte SIG[] = "DKIF"

component provides VideoFile:divf requires io.Output out, data.IntUtil iu {
	
	bool VideoFile:validHeader(byte content[])
		{
		Header hdr = new Header()
		dana.serial(hdr) =[] content

		if (hdr.signature != SIG)
			return false
		
		if (hdr.version != 0)
			return false
		
		return true
		}
	
	byte[] endianSwap(byte bytes[])
		{
		byte result[] = new byte[bytes.arrayLength]
		int rindex = result.arrayLength - 1
		for (int i = 0; i < result.arrayLength; i++)
			{
			result[rindex - i] = bytes[i]
			}

		return result
		}
	
	int4 endianSwapI4(int4 v)
		{
		Int4 val = new Int4(v)
		byte valStream[] = dana.serial(val)
		valStream =[] endianSwap(valStream)
		return val.value
		}
	
	int2 endianSwapI2(int2 v)
		{
		Int2 val = new Int2(v)
		byte valStream[] = dana.serial(val)
		valStream =[] endianSwap(valStream)
		return val.value
		}
	
	VideoHeader VideoFile:readHeader(byte content[])
		{
		if (!validHeader(content))
			{
			throw new Exception("invalid IVF video format header")
			}
		
		Header hdr = new Header()
		dana.serial(hdr) =[] content

		VideoHeader vh = new VideoHeader()
		vh.width = endianSwapI2(hdr.width)
		vh.height = endianSwapI2(hdr.height)
		vh.numerator = endianSwapI4(hdr.numerator)
		vh.denominator = endianSwapI4(hdr.denominator)

		vh.frames = endianSwapI4(hdr.frameCount)
		vh.fourcc =[] hdr.fourcc
		vh.headerLength = dana.serial(hdr).arrayLength

		return vh
		}
	
	VideoFrame VideoFile:readFrame(byte content[], int offset)
		{
		FrameHeader hdr = new FrameHeader()
		int hdrSize = dana.serial(hdr).arrayLength

		if (offset + hdrSize >= content.arrayLength)
			{
			return null
			}
		
		dana.serial(hdr) =[] dana.sub(content, offset, content.arrayLength - offset)
		hdr.frameSize = endianSwapI4(hdr.frameSize)
		offset += hdrSize

		if (offset + hdr.frameSize - 1 >= content.arrayLength)
			{
			throw new Exception("insufficient data for frame content")
			}
		
		//out.println("frame size at $(offset) is $(hdr.frameSize) bytes")

		byte frameData[] = dana.sub(content, offset, offset + hdr.frameSize - 1)
		
		return new VideoFrame(frameData, hdrSize, hdr.timestamp)
		}

}
Revision history
To propose a new revision to this entity, use dana source put -uc your/new/version.dn -n media.video.VideoFile:divf -m "reason for update" -u yourUsername
Version 2 by barry
Version 1 (this version) by barry
Notes for this version: Adds APIs for video decoding.