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 concatFiles() { log.Printf("Concat files: %#v", inFiles) if outFile == "" { log.Fatal("No output file") } outF, err := os.Create(outFile) if err != nil { log.Fatal(err) } defer outF.Close() frW := flv.NewWriter(outF) frWout := make(map[flv.TagType]*flv.FlvWriter) frWout[flv.TAG_TYPE_VIDEO] = frW frWout[flv.TAG_TYPE_AUDIO] = frW frWout[flv.TAG_TYPE_META] = frW wh := true // write header to output after read of first file offset := 0 for _, fn := range inFiles { inF, err := os.Open(fn) if err != nil { log.Fatal(err) } defer inF.Close() frReader, header, err := openFrameReader(inF) if err != nil { log.Fatal(err) } if wh { frW.WriteHeader(header) wh = false commonHeader = header } offset = writeFrames(frReader, frWout, offset) } }
func main() { flag.Usage = usage flag.Parse() defer closeSplitWriters() if isConcat { concatFiles() return } if inFile == "" { log.Fatal("No input file") } inF, err := os.Open(inFile) if err != nil { log.Fatal(err) } defer inF.Close() frReader, header, err := openFrameReader(inF) if err != nil { log.Fatal(err) } commonHeader = header if printInfo { printMetaData(frReader, printInfoKeys) return } else if flvDump { createMetaKeyframes(frReader) } else if splitContent { if outcFiles[flv.TAG_TYPE_VIDEO] == "" && outcFiles[flv.TAG_TYPE_AUDIO] == "" && outcFiles[flv.TAG_TYPE_META] == "" { log.Fatal("No any split output file") } type splitWriter struct { FileName string Writer *flv.FlvWriter } frFW := make(map[flv.TagType]*splitWriter) frFW[flv.TAG_TYPE_VIDEO] = &splitWriter{FileName: outcFiles[flv.TAG_TYPE_VIDEO], Writer: nil} frFW[flv.TAG_TYPE_AUDIO] = &splitWriter{FileName: outcFiles[flv.TAG_TYPE_AUDIO], Writer: nil} frFW[flv.TAG_TYPE_META] = &splitWriter{FileName: outcFiles[flv.TAG_TYPE_META], Writer: nil} frW := make(map[flv.TagType]*flv.FlvWriter) for k, _ := range frFW { var of string switch k { case flv.TAG_TYPE_VIDEO: of = outcFiles[flv.TAG_TYPE_VIDEO] case flv.TAG_TYPE_AUDIO: of = outcFiles[flv.TAG_TYPE_AUDIO] case flv.TAG_TYPE_META: of = outcFiles[flv.TAG_TYPE_META] } var pW *flv.FlvWriter = nil for wk, wv := range frFW { if wv.FileName == of { if wv.Writer != nil { log.Printf("Write %s to existing %s file %s", k, wk, of) pW = wv.Writer break } } } if pW != nil { frW[k] = pW } else { outF, err := os.Create(of) if err != nil { log.Fatal(err) } log.Printf("Write %s to %s", k, of) frFW[k].Writer = flv.NewWriter(outF) frFW[k].Writer.WriteHeader(header) frW[k] = frFW[k].Writer } } for _, v := range frW { defer v.OutFile.Close() } writeFrames(frReader, frW, 0) } else { if outFile == "" { log.Fatal("No output file") } outF, err := os.Create(outFile) if err != nil { log.Fatal(err) } defer outF.Close() frWriter := flv.NewWriter(outF) frWriter.WriteHeader(header) if updateKeyframes { inStart := writeMetaKeyframes(frReader, frWriter) inF.Seek(inStart, os.SEEK_SET) } frW := make(map[flv.TagType]*flv.FlvWriter) frW[flv.TAG_TYPE_VIDEO] = frWriter frW[flv.TAG_TYPE_AUDIO] = frWriter frW[flv.TAG_TYPE_META] = frWriter writeFrames(frReader, frW, 0) } }