Beispiel #1
0
func writeFrames(frReader *flv.FlvReader, frW map[flv.TagType]*flv.FlvWriter, offset int) (outOffset int) {
	lastTs := make(map[flv.TagType]map[uint32]uint32)
	lastTsDiff := make(map[flv.TagType]map[uint32]uint32)
	shiftTs := make(map[flv.TagType]map[uint32]uint32)
	for _, c := range []flv.TagType{flv.TAG_TYPE_VIDEO, flv.TAG_TYPE_AUDIO, flv.TAG_TYPE_META} {
		lastTs[c] = make(map[uint32]uint32)
		lastTsDiff[c] = make(map[uint32]uint32)
		shiftTs[c] = make(map[uint32]uint32)
	}

	updateDts := func(cframe flv.Frame) (newDts uint32) {
		c := cframe.GetType()
		s := cframe.GetStream()
		d := cframe.GetDts()
		if lastTs[c][s] > d {
			warnTs(lastTs[c][s], s, d)
			if fixDts {
				newDts := lastTs[c][s] + lastTsDiff[c][s]
				shiftTs[c][s] = newDts - d
				d += shiftTs[c][s]
			}
		}
		d = uint32(int(float64(d)*scaleDts) + offset)
		lastTsDiff[c][s] = d - lastTs[c][s]
		lastTs[c][s] = d
		return d
	}

	var lastInTs uint32 = 0
	var compensateTs uint32 = 0
	for {
		var rframe flv.Frame
		var err error
		var skipBytes int
		if readRecover {
			rframe, err, skipBytes = frReader.ReadFrameRecover(maxFrameSize)
		} else {
			rframe, err = frReader.ReadFrame()
		}
		if err != nil {
			log.Fatal(err)
		}
		if rframe != nil {
			if readRecover {
				if skipBytes > 0 {
					log.Printf("Recover: skip %d bytes, recovered frame length: %d", skipBytes, len(*rframe.GetBody()))
				}
				if rframe.GetType() == flv.TAG_TYPE_META {
					metaBody := rframe.GetBody()
					buf := bytes.NewReader(*metaBody)
					dec := amf0.NewDecoder(buf)
					_, err := dec.Decode()
					if err != nil {
						log.Printf("Bad metadata at DTS %d", rframe.GetDts())
						continue
					}
				}
			}
			isCrop := permitCrop(rframe)
			isSkip := permitSkip(rframe)
			isSplitStream := splitStreams && rframe.GetStream() != 0 && rframe.GetType() != flv.TAG_TYPE_META
			if (streams[rframe.GetType()] != -1 && rframe.GetStream() != uint32(streams[rframe.GetType()])) || isCrop || isSkip || isSplitStream {
				if compensateDts || isCrop {
					compensateTs += (rframe.GetDts() - lastInTs)
				}
				lastInTs = rframe.GetDts()
				if splitStreams {
					err = writeStreamFrame(rframe, outOffset)
					if err != nil {
						log.Fatal(err)
					}
				}
				continue
			}
			checkSplitWriters(outOffset)
			lastInTs = rframe.GetDts()
			newDts := updateDts(rframe) - compensateTs
			if rframe.GetStream() == 0 {
				outOffset = int(newDts)
			}
			rframe.SetDts(newDts)
			err = frW[rframe.GetType()].WriteFrame(rframe)
			if err != nil {
				log.Fatal(err)
			}
		} else {
			break
		}
	}
	return
}