How can I add new boxes , provided in my own assembly?

Jun 2, 2013 at 8:12 PM
I've added some boxes, avc1, avcC, btrt and mp4a into BmffViewer project.
It shows my added boxes fine.
But.
When I saved the mp4 file, the exception "Attempt to write past end of constrained region." was thrown.
I know the reason because CalculateSize() in Box class is 'internal virtual'
so my added classes can not override CalculateSize().

I think CalculateSize() should be 'public virtual'.

Please let me know right way to add those boxes in my project.

BR

ps. Is there any way to attach my source file? The file is not so small to put here (over 400lines).
Or, if nobody cares, I'll put whole souce code here.
Coordinator
Jun 3, 2013 at 1:19 AM
Ah, yes it should be protected virtual not internal virtual. It does need to be overridden in custom boxes even if they are in a separate assembly.

I'm not in a position to check in a fix right at this moment but feel free to change it in your copy and I'll update it soon.
Coordinator
Jun 3, 2013 at 1:34 AM
Also, I'm working on a way to deal with those box types you've added.

They don't actually need to be separate boxes. Unfortunately, the only way to determine which box structure to use for those is to look at the track header. There's only a couple of different ones and rather than do a box for every possible mediatype fourcc, it'd be better to do it generically. It's the only thing in the spec that requires knowledge from a different part of the file in order to properly decode a box's content. It means they can't be loaded and saved independent from the track and when you are deserializing, you have to be able to traverse up and back down the hierarchy to determine what type of box to deserialize.

It also means the containing box should warn you if you try to add the wrong child type and if you change the track type in the track header, it should somehow warn you of any mismatch there, too. There's not really any pretty way to do it, sadly.
Jun 3, 2013 at 7:58 AM
Thank you for the quick reply.
Ah, yes it should be protected virtual not internal virtual.
I don't think it should be protected but public.

In BaseMedia.cs:BaseMedia.GetBoxWriteSize() calls box.CalculateSize(),
BaseMedia class requires to access CalculateSize().

BaseMedia.GetBoxWriteSize() is required FastStart() in BaseMediaFile.cs.
At this point, FastStart() already knows instance of the box so FastStart() can call box.CalculateSize() directry.
It can remove protected BaseMedia.GetBoxWriteSize() from BaseMedia class.

And, if an application could call box.CalculateSize() directry,
the application could show calculated size when the application has edited contents of a box
(for example, add ChunkOffset entries to ChunkOffsetBox, ...).
Jun 3, 2013 at 8:00 AM
They don't actually need to be separate boxes.
Yes, it can be separately.
Some one wants to parse mp4, as I did.
Another one wants to parse 3gpp, mj2, F4v,...
These are based on ISO Base Media Format but have small differences.
Differences are defined by adding another boxes.
If your dlls were provided as
core BMFF
extention for mp4
extention for mj2
...
application(developper) can choise dlls to meet with the purpose, can implement himself.
This is the first reason I chose this.
Coordinator
Jun 3, 2013 at 9:33 AM
Ah, you are right.. public it is, then... I just don't like that because it shouldn't be a public api as its meant to be used internally for serialization. Shame C# doesn't have friend classes. Maybe I'll make it protected and a separate internal base class method that calls it and is called from BaseMedia. That'll make it properly overridable but not part of the public api.

As for the other, I think maybe we are talking at cross purposes. You mentioned avc1 and mp4a which are FOURCCs for specific track media types that can go in mov, mp4, 3gpp, f4v and other files all in pretty much the same way. Maybe you meant some other use of those. The library doesn't decode the box that says the media type of the track currently though it shows its FOURCC and a triangle with an exclamation in the viewer. There's more useful information in there if you decode the sub-boxes but you can't tell how without looking at the track header to see if its audio, video or text. Alternatively you could explicitly make a box for each fourcc but there are several hundred of those and they'll all end up being one of 4 different possible structures anyway.
Jun 3, 2013 at 10:09 AM
I've changed internal CalculateSize() to public.
When I grepped 'internal' , I found more 'internal's.

Box.cs
internal void Initialize(Stream stream, BaseMediaOptions options = BaseMediaOptions.LoadChildren)
could be protected.

protected internal void Sync(Stream stream, bool warn = true)
could be public (BaseMediaReader calls).
Jun 3, 2013 at 10:13 AM
I found bugs.

HandlerBox.cs
        public override ulong CalculateSize()
        {
            // 2013/06/03 Mizutama
            //return base.CalculateSize() + 4 + 4 + (4 * (ulong)_Reserved.Length) + (String.IsNullOrEmpty(Name) ? 0 : (ulong)Encoding.UTF8.GetByteCount(Name));
            return base.CalculateSize() + 4 + 4 + (4 * (ulong)_Reserved.Length)
                    + (String.IsNullOrEmpty( Name ) ? 0 : (ulong)(Encoding.UTF8.GetByteCount( Name ) + 1));
        }


        protected override void SaveToStream(Stream stream)
        {
            base.SaveToStream(stream);

            stream.WriteBEUInt32(_Predefined);
            stream.WriteBEUInt32(HandlerType);
            for (int i = 0; i < _Reserved.Length; i++) stream.WriteBEUInt32(_Reserved[i]);
            if(Name != null)
                //stream.WriteUTF8String(Name);                 // 2013/06/03 Mizutama
                stream.WriteNullTerminatedUTF8String( Name );   // 2013/06/03 Mizutama
        }
Jun 3, 2013 at 10:14 AM
I only want to see all boxes in my own mp4 files, without compiling/debugging the library itself.
I don't care the library has all boxes or not, if the library has some way to add boxes which are not implemented.
I'll do it.
Jun 3, 2013 at 10:42 AM
I didn't see the Issue 24101

Now you are going to fix it.

You said
By the way, this appears to be a convention not specification.
The QT format notes repeatedly that 0 length strings at the end of an atom can be either 0
or simply not present but doesn't say anything specific about non-zero strings.
But I saw
ISO/IEC 14496-12 Part 12: ISO base media file format Third edition 2008-10-15
8.4.3.3 Semantics
name is a null-terminated string in UTF-8 characters which gives a human-readable name for the track
type (for debugging and inspection purposes).

Actually, Windows Media Player became an error when the mp4 had non-null terminated name in HandlerBox.