amf0 add write

This commit is contained in:
nareix 2016-06-23 00:33:01 +08:00
parent 855efc4f5d
commit 8685b4f4ad

View File

@ -2,6 +2,7 @@ package flvio
import ( import (
"math" "math"
"fmt"
"time" "time"
"github.com/nareix/pio" "github.com/nareix/pio"
) )
@ -9,17 +10,24 @@ import (
type AMFMap map[string]interface{} type AMFMap map[string]interface{}
type AMFArray []interface{} type AMFArray []interface{}
func readBEFloat64(r *pio.Reader) (f64 float64, err error) { func readBEFloat64(r *pio.Reader) (f float64, err error) {
var u64 uint64 var u uint64
if u64, err = r.ReadU64BE(); err != nil { if u, err = r.ReadU64BE(); err != nil {
return return
} }
f64 = math.Float64frombits(u64) f = math.Float64frombits(u)
return return
} }
func ReadAMF0Val(r *pio.Reader) (val interface{}, err error) { func writeBEFloat64(w *pio.Writer, f float64) (err error) {
const ( u := math.Float64bits(f)
if err = w.WriteU64BE(u); err != nil {
return
}
return
}
const (
numbermarker = iota numbermarker = iota
booleanmarker booleanmarker
stringmarker stringmarker
@ -37,8 +45,134 @@ func ReadAMF0Val(r *pio.Reader) (val interface{}, err error) {
recordsetmarker recordsetmarker
xmldocumentmarker xmldocumentmarker
typedobjectmarker typedobjectmarker
) )
func writeAMF0Number(w *pio.Writer, f float64) (err error) {
if err = w.WriteU8(numbermarker); err != nil {
return
}
if err = writeBEFloat64(w, f); err != nil {
return
}
return
}
func WriteAMF0Val(w *pio.Writer, _val interface{}) (err error) {
switch val := _val.(type) {
case int8:
return writeAMF0Number(w, float64(val))
case int16:
return writeAMF0Number(w, float64(val))
case int32:
return writeAMF0Number(w, float64(val))
case int64:
return writeAMF0Number(w, float64(val))
case uint8:
return writeAMF0Number(w, float64(val))
case uint16:
return writeAMF0Number(w, float64(val))
case uint32:
return writeAMF0Number(w, float64(val))
case uint64:
return writeAMF0Number(w, float64(val))
case float32:
return writeAMF0Number(w, float64(val))
case float64:
return writeAMF0Number(w, val)
case string:
u := len(val)
if u > 65536 {
if err = w.WriteU8(stringmarker); err != nil {
return
}
if err = w.WriteU16BE(uint16(u)); err != nil {
return
}
} else {
if err = w.WriteU8(longstringmarker); err != nil {
return
}
if err = w.WriteU32BE(uint32(u)); err != nil {
return
}
}
if _, err = w.Write([]byte(val)); err != nil {
return
}
case AMFMap:
if err = w.WriteU8(objectmarker); err != nil {
return
}
for k, v := range val {
if len(k) > 0 {
if err = WriteAMF0Val(w, k); err != nil {
return
}
if err = WriteAMF0Val(w, v); err != nil {
return
}
}
}
if err = w.WriteU16BE(0); err != nil {
return
}
case AMFArray:
if err = w.WriteU8(strictarraymarker); err != nil {
return
}
if err = w.WriteU32BE(uint32(len(val))); err != nil {
return
}
for _, v := range val {
if err = WriteAMF0Val(w, v); err != nil {
return
}
}
case time.Time:
if err = w.WriteU8(datemarker); err != nil {
return
}
u := val.UnixNano()
f := float64(u/1000000)
if err = writeBEFloat64(w, f); err != nil {
return
}
if err = w.WriteU16BE(0); err != nil {
return
}
case bool:
if err = w.WriteU8(booleanmarker); err != nil {
return
}
var u uint8
if val {
u = 1
} else {
u = 0
}
if err = w.WriteU8(u); err != nil {
return
}
case nil:
if err = w.WriteU8(nullmarker); err != nil {
return
}
default:
err = fmt.Errorf("amf0: write: invalid val=%v", val)
return
}
return
}
func ReadAMF0Val(r *pio.Reader) (val interface{}, err error) {
var marker uint8 var marker uint8
if marker, err = r.ReadU8(); err != nil { if marker, err = r.ReadU8(); err != nil {
return return
@ -156,6 +290,10 @@ func ReadAMF0Val(r *pio.Reader) (val interface{}, err error) {
return return
} }
val = string(b) val = string(b)
default:
err = fmt.Errorf("amf0: read: invalid marker=%d", marker)
return
} }
return return