func writeStreamFrame(rframe flv.Frame, baseDts int) (err error) { if streamsWriters == nil { streamsWriters = make(map[uint32]*streamWriter) } stream := rframe.GetStream() var stWr *streamWriter if _, ok := streamsWriters[stream]; !ok { log.Printf("Write new stream %d from dts %d", stream, baseDts) splitFileNumber++ stWr = new(streamWriter) stWr.fileName = fmt.Sprintf("n-%05d-ts-%d-s-%d.flv", splitFileNumber, baseDts, stream) stWr.fd, err = os.Create(stWr.fileName) if err != nil { log.Fatalf("Cannot open file %s: %s", stWr.fileName, err.Error()) } stWr.writer = flv.NewWriter(stWr.fd) stWr.writer.WriteHeader(commonHeader) stWr.firstDts = baseDts stWr.offsetDts = rframe.GetDts() streamsWriters[stream] = stWr } else { stWr = streamsWriters[stream] } rframe.SetDts(rframe.GetDts() - stWr.offsetDts) stWr.writer.WriteFrame(rframe) stWr.lastDts = baseDts return nil }
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 rframe, rerr := frReader.ReadFrame() switch { case rerr != nil && !readRecover: log.Fatal(rerr) case rerr != nil && rerr.IsRecoverable(): rframe, err, skipBytes = frReader.Recover(rerr, maxScanSize) if err != nil { log.Fatalf("recovery error: %s", err) } log.Printf("recover: got fine frame after %d bytes", skipBytes) continue } if rframe != nil { // 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 }