write.go (1437B)
1 package mp4 2 3 import ( 4 "errors" 5 "io" 6 ) 7 8 type Writer struct { 9 writer io.WriteSeeker 10 biStack []*BoxInfo 11 } 12 13 func NewWriter(w io.WriteSeeker) *Writer { 14 return &Writer{ 15 writer: w, 16 } 17 } 18 19 func (w *Writer) Write(p []byte) (int, error) { 20 return w.writer.Write(p) 21 } 22 23 func (w *Writer) Seek(offset int64, whence int) (int64, error) { 24 return w.writer.Seek(offset, whence) 25 } 26 27 func (w *Writer) StartBox(bi *BoxInfo) (*BoxInfo, error) { 28 bi, err := WriteBoxInfo(w.writer, bi) 29 if err != nil { 30 return nil, err 31 } 32 w.biStack = append(w.biStack, bi) 33 return bi, nil 34 } 35 36 func (w *Writer) EndBox() (*BoxInfo, error) { 37 bi := w.biStack[len(w.biStack)-1] 38 w.biStack = w.biStack[:len(w.biStack)-1] 39 end, err := w.writer.Seek(0, io.SeekCurrent) 40 if err != nil { 41 return nil, err 42 } 43 bi.Size = uint64(end) - bi.Offset 44 if _, err = bi.SeekToStart(w.writer); err != nil { 45 return nil, err 46 } 47 if bi2, err := WriteBoxInfo(w.writer, bi); err != nil { 48 return nil, err 49 } else if bi.HeaderSize != bi2.HeaderSize { 50 return nil, errors.New("header size changed") 51 } 52 if _, err := w.writer.Seek(end, io.SeekStart); err != nil { 53 return nil, err 54 } 55 return bi, nil 56 } 57 58 func (w *Writer) CopyBox(r io.ReadSeeker, bi *BoxInfo) error { 59 if _, err := bi.SeekToStart(r); err != nil { 60 return err 61 } 62 if n, err := io.CopyN(w, r, int64(bi.Size)); err != nil { 63 return err 64 } else if n != int64(bi.Size) { 65 return errors.New("failed to copy box") 66 } 67 return nil 68 }