Pregunta

I am creating my own video file format and would like to write out a file header and frame headers.

At the moment I just have placeholders defined as such:

byte[] fileHeader = new byte[FILE_HEADER_SIZE * sizeof(int)];
byte[] frameHeader = new byte[FRAME_HEADER_SIZE * sizeof(int)];

I write them out using the following for the file header:

fsVideoWriter.Write(fileHeader, 0, FILE_HEADER_SIZE);

and this for the frame headers:

fsVideoWriter.Write(frameHeader, 0, FRAME_HEADER_SIZE);

Now that I actually need to make proper use of these headers, I'm not sure if this would be the most convenient way to write them, as I am not sure if it will be easy to read in the individual fields I need into separate variables from the headers.

I thought about doing something like the following:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct FileHeader
{
    public int x;
    public int y;
    public int z;
            // etc. etc.
}

I would like to define it in such a way that I can upgrade easily as the file format evolves, (i.e. including a version number). Is this the recommended way to define a file/frame header? If so, how should I read/write it using the .NET FileStream class? If this is not the recommended way, please suggest the proper way to do this, as maybe someone has already created a generic video file-related class that handles this sort of thing?

¿Fue útil?

Solución

I settled upon the following solution:

Writing out file header

public static bool WriteFileHeader(FileStream fileStream, FileHeader fileHeader)
{
    try
    {
        byte[] buffer = new byte[FILE_HEADER_SIZE];

        GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        Marshal.StructureToPtr(fileHeader, gch.AddrOfPinnedObject(), false);
        gch.Free();

        fileStream.Seek(0, SeekOrigin.Begin);                
        fileStream.Write(buffer, 0, FILE_HEADER_SIZE);

        return true;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

Reading in file header

public static bool ReadFileHeader(FileStream fileStream, out FileHeader fileHeader)
{
    try
    {
        fileHeader = new FileHeader();

        byte[] buffer = new byte[FILE_HEADER_SIZE];

        fileStream.Seek(0, SeekOrigin.Begin);
        fileStream.Read(buffer, 0, FILE_HEADER_SIZE);

        GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        Marshal.PtrToStructure(gch.AddrOfPinnedObject(), fileHeader);

        gch.Free();

        // test for valid data
        boolean isSuccessful = IsValidHeader(fileHeader);

        return isSuccessful;

    }
    catch (Exception ex)
    {
        throw ex;
    }

}

I used a similar approach for the frame headers as well. The idea is basically to make use of byte buffers and Marshal.

Otros consejos

You may want to try the BinaryFormatter Class. But it is more or less a black box. If you need precise control of your file format, you can write your own Formatter and use it to serialize your header object.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top