github.com/cnotch/ipchub@v1.1.0/av/format/amf/object.go (about)

     1  // Copyright (c) 2019,CAOHONGJU All rights reserved.
     2  // Use of this source code is governed by a MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package amf
     6  
     7  import (
     8  	"encoding/binary"
     9  	"fmt"
    10  	"io"
    11  )
    12  
    13  // ObjectProperty amf 对象属性
    14  type ObjectProperty struct {
    15  	Name  string
    16  	Value interface{}
    17  }
    18  
    19  // PropertyValue  获取属性数组中指定属性名的值
    20  func PropertyValue(properties []ObjectProperty, name string) (value interface{}, ok bool) {
    21  	for _, prop := range properties {
    22  		if name == prop.Name {
    23  			return prop.Value, true
    24  		}
    25  	}
    26  	return nil, false
    27  }
    28  
    29  // EcmaArray 表示 TypeEcmaArray 类型存储的值
    30  type EcmaArray []ObjectProperty
    31  
    32  // ReadEcmaArray .
    33  func ReadEcmaArray(r io.Reader) (value EcmaArray, err error) {
    34  	var buff [1]byte
    35  	if _, err = io.ReadFull(r, buff[:]); err != nil {
    36  		return
    37  	}
    38  
    39  	if TypeEcmaArray != buff[0] {
    40  		err = fmt.Errorf("Amf0ReadEcmaArray: TypeEcmaArray != marker")
    41  		return
    42  	}
    43  	return readEcmaArray(r)
    44  }
    45  
    46  func readEcmaArray(r io.Reader) (value EcmaArray, err error) {
    47  	var buff [4]byte
    48  	if _, err = io.ReadFull(r, buff[:]); err != nil {
    49  		return
    50  	}
    51  
    52  	count := int(binary.BigEndian.Uint32(buff[:]))
    53  	value = make(EcmaArray, 0, count)
    54  	for {
    55  		var elem ObjectProperty
    56  		if elem.Name, err = readUtf8(r, 2); err != nil {
    57  			return
    58  		}
    59  
    60  		if elem.Value, err = ReadAny(r); err != nil {
    61  			return
    62  		}
    63  
    64  		// 判断是否是 ObjectEnd
    65  		if _, ok := elem.Value.(objectEndValue); ok && len(elem.Name) == 0 {
    66  			break
    67  		}
    68  
    69  		value = append(value, elem)
    70  	}
    71  
    72  	if len(value) != count {
    73  		err = fmt.Errorf("Does not match the expected length of the array and the actual; expected = %d ,actual = %d", count, len(value))
    74  	}
    75  	return
    76  }
    77  
    78  // WriteEcmaArray .
    79  func WriteEcmaArray(w io.Writer, arr EcmaArray) (err error) {
    80  	var buff [5]byte
    81  
    82  	buff[0] = TypeEcmaArray
    83  	binary.BigEndian.PutUint32(buff[1:], uint32(len(arr)))
    84  	if _, err = w.Write(buff[:]); err != nil {
    85  		return
    86  	}
    87  
    88  	for _, elem := range arr {
    89  		if err = writeUtf8(w, elem.Name, 2); err != nil {
    90  			return
    91  		}
    92  		if err = WriteAny(w, elem.Value); err != nil {
    93  			return
    94  		}
    95  	}
    96  
    97  	//eof
    98  	if _, err = w.Write([]byte{0x00, 0x00, TypeObjectEnd}); err != nil {
    99  		return
   100  	}
   101  	return
   102  }
   103  
   104  // Object 表示 TypeObject 类型存储的值
   105  type Object []ObjectProperty
   106  
   107  // ReadObject .
   108  func ReadObject(r io.Reader) (value Object, err error) {
   109  	var data [1]byte
   110  	if _, err = io.ReadFull(r, data[:]); err != nil {
   111  		return
   112  	}
   113  
   114  	if TypeObject != data[0] {
   115  		err = fmt.Errorf("Amf0ReadObject: TypeObject != marker")
   116  		return
   117  	}
   118  	return readObject(r)
   119  }
   120  
   121  func readObject(r io.Reader) (value Object, err error) {
   122  	for {
   123  		var prop ObjectProperty
   124  		if prop.Name, err = readUtf8(r, 2); err != nil {
   125  			return
   126  		}
   127  
   128  		if prop.Value, err = ReadAny(r); err != nil {
   129  			return
   130  		}
   131  
   132  		// 判断是否是 ObjectEnd
   133  		if _, ok := prop.Value.(objectEndValue); ok && len(prop.Name) == 0 {
   134  			break
   135  		}
   136  		value = append(value, prop)
   137  	}
   138  
   139  	return
   140  }
   141  
   142  // WriteObject .
   143  func WriteObject(w io.Writer, obj Object) (err error) {
   144  	buff := [1]byte{TypeObject}
   145  	if _, err = w.Write(buff[:]); err != nil {
   146  		return
   147  	}
   148  
   149  	for _, prop := range obj {
   150  		if err = writeUtf8(w, prop.Name, 2); err != nil {
   151  			return
   152  		}
   153  		if err = WriteAny(w, prop.Value); err != nil {
   154  			return
   155  		}
   156  	}
   157  
   158  	//eof
   159  	if _, err = w.Write([]byte{0x00, 0x00, TypeObjectEnd}); err != nil {
   160  		return
   161  	}
   162  
   163  	return
   164  }
   165  
   166  // StrictArray 表示 TypeStrictArray 类型存储的值
   167  type StrictArray []interface{}
   168  
   169  // ReadStrictArray .
   170  func ReadStrictArray(r io.Reader) (value StrictArray, err error) {
   171  	var buff [1]byte
   172  	if _, err = io.ReadFull(r, buff[:]); err != nil {
   173  		return
   174  	}
   175  
   176  	if TypeStrictArray != buff[0] {
   177  		err = fmt.Errorf("Amf0ReadStrictArray: TypeStrictArray != marker")
   178  		return
   179  	}
   180  	return readStrictArray(r)
   181  }
   182  
   183  func readStrictArray(r io.Reader) (value StrictArray, err error) {
   184  	var buff [4]byte
   185  	if _, err = io.ReadFull(r, buff[:]); err != nil {
   186  		return
   187  	}
   188  
   189  	count := int(binary.BigEndian.Uint32(buff[:]))
   190  
   191  	for i := 0; i < count; i++ {
   192  		var elem interface{}
   193  		elem, err = ReadAny(r)
   194  		value = append(value, elem)
   195  	}
   196  
   197  	return
   198  }
   199  
   200  // WriteStrictArray .
   201  func WriteStrictArray(w io.Writer, arr StrictArray) (err error) {
   202  	var buff [5]byte
   203  
   204  	buff[0] = TypeStrictArray
   205  	binary.BigEndian.PutUint32(buff[1:], uint32(len(arr)))
   206  
   207  	for _, elem := range arr {
   208  		if err = WriteAny(w, elem); err != nil {
   209  			return
   210  		}
   211  	}
   212  	return
   213  }