123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- package model
- import (
- "bytes"
- "compress/gzip"
- "encoding/binary"
- "encoding/json"
- "fmt"
- "io/ioutil"
- )
- var (
- _defaultSeg = &Segment{Start: 0, End: defaultVideoEnd, Cnt: 1, Num: 1, Duration: 0}
- // DefaultFlag default dm flag if bigdata downgrade.
- DefaultFlag = []byte(`{"rec_flag":2,"rec_text":"开启后,全站视频将按等级等优化弹幕","rec_switch":1,"dmflags":[]}`)
- )
- const (
- // segmentLength 分段长度,6分钟
- segmentLength = 60 * 6 * 1000
- // defaultVideoEnd 当视频时长不存在或者为0时的默认视频结尾时间点
- defaultVideoEnd = int64(10 * 60 * 60 * 1000)
- // DefaultVideoEnd 当视频时长不存在或者为0时的默认视频结尾时间点
- DefaultVideoEnd = int64(3 * 60 * 60 * 1000)
- // DefaultPageSize 默认分段长度
- DefaultPageSize = 60 * 6 * 1000
- // NotFound nothing found flag
- NotFound = int64(-1)
- // DefaultPage default page info
- // <d p="弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id">弹幕内容</d>
- _xmlSegFmt = `<d p="%d,%d,%d,%d,%d,%d,%d,%d,%s">%s</d>`
- // <d p="弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id,用户mid">弹幕内容</d>
- _xmlSegRealnameFmt = `<d p="%d,%d,%d,%d,%d,%d,%d,%d,%s,%d">%s</d>`
- _xmlSegHeader = `<?xml version="1.0" encoding="UTF-8"?><i><oid>%d</oid><ps>%d</ps><pe>%d</pe><pc>%d</pc><pn>%d</pn><state>%d</state><real_name>%d</real_name>`
- )
- // JudgeSlice sort for dm judgement
- type JudgeSlice []*DM
- func (d JudgeSlice) Len() int { return len(d) }
- func (d JudgeSlice) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
- func (d JudgeSlice) Less(i, j int) bool { return d[i].Progress < d[j].Progress }
- // Segment dm segment struct
- type Segment struct {
- Start int64 `json:"ps"` // 分段起始时间
- End int64 `json:"pe"` // 分段结束时间
- Cnt int64 `json:"cnt"` // 总分段数
- Num int64 `json:"num"` // 当前第几段
- Duration int64 `json:"duration"` // 视频总时长
- }
- // DMSegResp segment dm list response
- type DMSegResp struct {
- Dms []*Elem `json:"dms"`
- Flag json.RawMessage `json:"flags,omitempty"`
- }
- // Page page info.
- type Page struct {
- Num int64 `json:"num"`
- Size int64 `json:"size"`
- Total int64 `json:"total"`
- }
- // ToXMLHeader convert segment to xml header format.
- func (s *Segment) ToXMLHeader(oid int64, state, realname int32) string {
- return fmt.Sprintf(_xmlSegHeader, oid, s.Start, s.End, s.Cnt, s.Num, state, realname)
- }
- // SegmentInfo get segment info by start time and video duration.
- func SegmentInfo(ps, duration int64) (s *Segment) {
- var cnt, num, pe int64
- if duration == 0 {
- s = _defaultSeg
- return
- }
- cnt = duration / segmentLength
- if duration%segmentLength > 0 {
- cnt++
- }
- for i := int64(0); i < cnt; i++ {
- if ps >= i*segmentLength && ps < (i+1)*segmentLength {
- ps = i * segmentLength
- pe = (i + 1) * segmentLength
- num = i + 1
- }
- }
- if pe > duration {
- pe = duration
- }
- s = &Segment{
- Start: ps,
- End: pe,
- Cnt: cnt,
- Num: num,
- Duration: duration,
- }
- return
- }
- // Encode dm ecode.
- func Encode(flag, xml []byte) (res []byte) {
- var (
- fl = uint32(len(flag))
- xl = uint32(len(xml))
- )
- res = make([]byte, 4+fl+xl)
- binary.BigEndian.PutUint32(res[0:4], fl)
- copy(res[4:], flag)
- copy(res[4+fl:], xml)
- return
- }
- // Decode decode dm proto.
- func Decode(buf []byte) (flag, xml []byte, err error) {
- var (
- zr *gzip.Reader
- )
- fl := binary.BigEndian.Uint32(buf[0:4])
- flag = buf[4 : 4+fl]
- if zr, err = gzip.NewReader(bytes.NewBuffer(buf[4+fl:])); err != nil {
- return
- }
- zr.Close()
- if xml, err = ioutil.ReadAll(zr); err != nil {
- return
- }
- return
- }
- // ToElem convert dm struct to element.
- func (d *DM) ToElem() (e *Elem) {
- if d.Content == nil {
- return
- }
- msg := d.Content.Msg
- if d.ContentSpe != nil {
- msg = d.ContentSpe.Msg
- }
- if len(msg) == 0 {
- return
- }
- if d.Pool == PoolSpecial {
- msg = ""
- }
- // "弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id
- e = &Elem{
- Attribute: fmt.Sprintf(`"%d,%d,%d,%d,%d,%d,%d,%d,%s"`, d.ID, d.Attr, d.Progress, d.Content.Mode, d.Content.FontSize, d.Content.Color, d.Ctime, d.Pool, Hash(d.Mid, uint32(d.Content.IP))),
- Content: msg,
- }
- return
- }
|