func (c *DemuxerClient) ParseBlockGroup(buf []byte) bool { if c.clusterTimecode == -1 { panic("Got a block group before the cluster timecode.") } typeInfo := map[int]int{ webm.IdBlock: ebml.TypeBinary, webm.IdBlockAdditions: ebml.TypeBinary, webm.IdBlockDuration: ebml.TypeUint, webm.IdReferenceBlock: ebml.TypeInt, webm.IdDiscardPadding: ebml.TypeInt, } bw := ebml.NewBufferWriter(len(buf)) bc := &BlockGroupClient{parsedBlock: false, writer: ebml.NewWriter(bw)} p := ebml.NewParser(ebml.GetListIDs(typeInfo), webm.UnknownSizeInfo(), ebml.NewElementParser(bc, typeInfo)) if !p.Append(buf) { log.Printf("Parser error") return false } p.EndOfData() id := bc.id rawTimecode := bc.rawTimecode flags := bc.flags timecode := c.clusterTimecode + rawTimecode //log.Printf("in track %d %d 0x%x %d\n", id, timecode, flags, len(buf)-3-idSize) if c.startTimecode == -1 { c.startTimecode = timecode } blockList, ok := c.blocks[id] if !ok { return false } c.blocks[id] = append(blockList, NewBlock(id, false, timecode, flags, bc.blockData, bw.Bytes())) c.tryWritingNextBlock() return true }
func main() { var minClusterDurationInMS int flag.IntVar(&minClusterDurationInMS, "cm", 250, "Minimum Cluster Duration (ms)") flag.Parse() if minClusterDurationInMS < 0 || minClusterDurationInMS > 30000 { log.Printf("Invalid minimum cluster duration\n") os.Exit(-1) } if len(flag.Args()) < 2 { log.Printf("Usage: %s [-cm <duration>] <infile> <outfile>\n", os.Args[0]) return } var in *os.File = nil var err error = nil inputArg := flag.Arg(0) outputArg := flag.Arg(1) if inputArg == "-" { in = os.Stdin } else { in, err = os.Open(inputArg) checkError("Open input", err) } var out *ebml.Writer = nil if outputArg == "-" { out = ebml.NewNonSeekableWriter(io.WriteSeeker(os.Stdout)) } else { if inputArg == outputArg { log.Printf("Input and output filenames can't be the same.\n") return } if strings.HasPrefix(outputArg, "ws://") { url, err := url.Parse(outputArg) checkError("Output url", err) origin := "http://localhost/" ws, err := websocket.Dial(url.String(), "", origin) checkError("WebSocket Dial", err) out = ebml.NewNonSeekableWriter(io.Writer(ws)) } else { file, err := os.Create(outputArg) if err != nil { log.Printf("Failed to create '%s'; err=%s\n", outputArg, err.Error()) os.Exit(1) } out = ebml.NewWriter(io.WriteSeeker(file)) } } buf := [1024]byte{} c := NewDemuxerClient(out, minClusterDurationInMS) typeInfo := map[int]int{ ebml.IdHeader: ebml.TypeBinary, webm.IdSegment: ebml.TypeList, webm.IdInfo: ebml.TypeBinary, webm.IdTracks: ebml.TypeBinary, webm.IdCluster: ebml.TypeList, webm.IdTimecode: ebml.TypeUint, webm.IdSimpleBlock: ebml.TypeBinary, } parser := ebml.NewParser(ebml.GetListIDs(typeInfo), webm.UnknownSizeInfo(), ebml.NewElementParser(c, typeInfo)) for done := false; !done; { bytesRead, err := in.Read(buf[:]) if err == io.EOF || err == io.ErrClosedPipe { parser.EndOfData() done = true continue } if !parser.Append(buf[0:bytesRead]) { log.Printf("Parser error") done = true continue } } }