├── .gitignore ├── README.md ├── gohevc.go └── hevc ├── cu.go ├── data.go ├── frame.go ├── helper.go ├── lcu.go ├── parser.go ├── pps.go ├── ps.go ├── pu.go ├── slice.go ├── sps.go ├── tu.go └── vps.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GoVisa 2 | ======= 3 | 4 | H.265/HEVC Bitstream Analyzer in Go 5 | 6 | /* The copyright in this software is being made available under the BSD 7 | * License, included below. This software may be subject to other third party 8 | * and contributor rights, including patent rights, and no such rights are 9 | * granted under this license. 10 | * 11 | * Copyright (c) 2012-2013, H265.net 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without 15 | * modification, are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * * Redistributions in binary form must reproduce the above copyright notice, 20 | * this list of conditions and the following disclaimer in the documentation 21 | * and/or other materials provided with the distribution. 22 | * * Neither the name of the H265.net nor the names of its contributors may 23 | * be used to endorse or promote products derived from this software without 24 | * specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 36 | * THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | -------------------------------------------------------------------------------- /gohevc.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package main 35 | 36 | import ( 37 | "fmt" 38 | "bufio" 39 | "os" 40 | "os/exec" 41 | "log" 42 | "gohevc/hevc" 43 | ) 44 | 45 | func main() { 46 | fmt.Printf("GoHEVC Analyzer %v for HM\n\n", hevc.Version) 47 | 48 | if len(os.Args)==3 { 49 | var cmd *exec.Cmd 50 | const refYUV = "temp.yuv" 51 | 52 | if os.Args[2]=="hm80" { 53 | cmd = exec.Command("TAppDecoder80", "-b", os.Args[1], "-o", refYUV) 54 | }else if os.Args[2]=="hm90" { 55 | cmd = exec.Command("TAppDecoder90", "-b", os.Args[1], "-o", refYUV) 56 | }else if os.Args[2]=="hm91" { 57 | cmd = exec.Command("TAppDecoder91", "-b", os.Args[1], "-o", refYUV) 58 | }else{ 59 | fmt.Printf("Unsupported HM Version\n"); 60 | return 61 | } 62 | fmt.Printf("Decoding %s", os.Args[1]) 63 | 64 | out, err := cmd.Output() 65 | if err != nil { 66 | log.Fatal(err) 67 | } else{ 68 | fmt.Printf("%s\n", out) 69 | 70 | fmt.Printf("\nAnalyzing %s\n", os.Args[1]) 71 | 72 | traceFile, err := os.Open("TraceDec.txt"); 73 | if err!=nil { 74 | log.Fatal(err) 75 | } 76 | defer traceFile.Close() 77 | 78 | yuvFile, err := os.Open(refYUV); 79 | if err!=nil { 80 | log.Fatal(err) 81 | } 82 | defer yuvFile.Close() 83 | 84 | var ha hevc.Analyzer 85 | 86 | if err = ha.ParseTrace(traceFile); err!=nil { 87 | log.Fatal(err) 88 | }else{ 89 | if err = ha.ParseYUV(yuvFile); err !=nil { 90 | log.Fatal(err) 91 | }else{ 92 | ha.ParseCmd(os.Args[1], bufio.NewReader(os.Stdin), string(out)) 93 | } 94 | } 95 | } 96 | }else{ 97 | fmt.Printf("Usage: gohevc.exe bitstream.265 hmversion(hm80/hm90/hm91)\n") 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /hevc/cu.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | //"fmt" 38 | //"errors" 39 | "bufio" 40 | "container/list" 41 | ) 42 | 43 | 44 | type CU struct { 45 | ParameterSet 46 | PUList *list.List 47 | TUList *list.List 48 | M_lcu *LCU 49 | Cu_x int 50 | Cu_y int 51 | Cu_size int 52 | } 53 | 54 | 55 | func NewCU(reader *bufio.Reader) *CU{ 56 | var cu CU 57 | 58 | cu.ParameterSet.Reader = reader 59 | cu.ParameterSet.FieldList = list.New() 60 | cu.PUList = list.New() 61 | cu.TUList = list.New() 62 | 63 | return &cu 64 | } 65 | 66 | func (ps *CU) Parse() (line string, err error) { 67 | line, err = ps.ParameterSet.Parse() 68 | 69 | ps.Cu_x, err = ps.ParameterSet.GetValue("cu_x") 70 | if err != nil { 71 | return line, err 72 | } 73 | 74 | ps.Cu_y, err = ps.ParameterSet.GetValue("cu_y") 75 | if err != nil { 76 | return line, err 77 | } 78 | 79 | ps.Cu_size, err = ps.ParameterSet.GetValue("cu_size") 80 | 81 | return line, err 82 | } 83 | -------------------------------------------------------------------------------- /hevc/data.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | "fmt" 38 | "io" 39 | "bufio" 40 | "errors" 41 | "strings" 42 | "strconv" 43 | ) 44 | 45 | 46 | const ( 47 | TCOEF = iota 48 | TPEL 49 | TPXL 50 | ) 51 | 52 | type DATA struct { 53 | YUVReader io.Reader 54 | Reader *bufio.Reader 55 | //M_frame *Frame 56 | //M_tu *TU 57 | M_data [][]int 58 | M_color int 59 | M_tu_x int 60 | M_tu_y int 61 | M_width int 62 | M_height int 63 | M_type int 64 | } 65 | 66 | 67 | func NewDATA(reader *bufio.Reader, tu_color, tu_x, tu_y, tu_width, tu_height, pixel_type int) *DATA{ 68 | var ps DATA 69 | 70 | ps.Reader = reader 71 | ps.M_color = tu_color 72 | ps.M_tu_x = tu_x 73 | ps.M_tu_y = tu_y 74 | ps.M_width = tu_width 75 | ps.M_height = tu_height 76 | ps.M_type = pixel_type 77 | 78 | ps.M_data = make([][]int, tu_height) 79 | for j:= 0; j=ps.M_height { 124 | line = "" 125 | err = errors.New("more data than expected") 126 | return line, err 127 | }else{ 128 | var value int64 129 | coef_str := strings.Fields(strings.TrimSpace(line)) 130 | 131 | for i:=0; i>chroma)+tu_y+j][(cu_x>>chroma)+tu_x+i] 94 | } 95 | } 96 | } 97 | } 98 | 99 | return &final 100 | } 101 | 102 | func (frame *Frame) ShowTileSummary() { 103 | fmt.Printf("============================================================================\n",) 104 | 105 | tiles_enabled_flag_type, tiles_enabled_flag, err := frame.M_pps.GetTypeValue("tiles_enabled_flag") 106 | if err!=nil{ 107 | tiles_enabled_flag_type, tiles_enabled_flag, err = frame.M_pps.GetTypeValue("tiles_or_entropy_coding_sync_idc") 108 | 109 | if err!=nil { 110 | fmt.Printf("tiles_enabled_flag not found\n") 111 | return 112 | }else{ 113 | fmt.Printf("%-62s %-6s: %4d\n", "tiles_or_entropy_coding_sync_idc", tiles_enabled_flag_type, tiles_enabled_flag) 114 | } 115 | }else{ 116 | fmt.Printf("%-62s %-6s: %4d\n", "tiles_enabled_flag", tiles_enabled_flag_type, tiles_enabled_flag) 117 | } 118 | 119 | if tiles_enabled_flag==1{ 120 | num_tile_columns_minus1_type, num_tile_columns_minus1, _ := frame.M_pps.GetTypeValue("num_tile_columns_minus1") 121 | fmt.Printf("%-62s %-6s: %4d\n", "num_tile_columns_minus1", num_tile_columns_minus1_type, num_tile_columns_minus1) 122 | 123 | num_tile_rows_minus1_type, num_tile_rows_minus1, _ := frame.M_pps.GetTypeValue("num_tile_rows_minus1") 124 | fmt.Printf("%-62s %-6s: %4d\n", "num_tile_rows_minus1", num_tile_rows_minus1_type, num_tile_rows_minus1) 125 | 126 | uniform_spacing_flag_type, uniform_spacing_flag, _ := frame.M_pps.GetTypeValue("uniform_spacing_flag") 127 | fmt.Printf("%-62s %-6s: %4d\n", "uniform_spacing_flag", uniform_spacing_flag_type, uniform_spacing_flag) 128 | 129 | if uniform_spacing_flag != 1 { 130 | for i := 0; i < num_tile_columns_minus1; i = i+1 { 131 | t, v, _ := frame.M_pps.GetTypeValue("column_width_minus1[i]") 132 | fmt.Printf("%-62s %-6s: %4d\n", "column_width_minus1[i]", t, v) 133 | } 134 | 135 | for i := 0; i < num_tile_rows_minus1; i = i+1 { 136 | t, v, _ := frame.M_pps.GetTypeValue("row_height_minus1[i]") 137 | fmt.Printf("%-62s %-6s: %4d\n", "row_height_minus1[i]", t, v) 138 | } 139 | } 140 | 141 | loop_filter_across_tiles_enabled_flag_type, loop_filter_across_tiles_enabled_flag, _ := frame.M_pps.GetTypeValue("loop_filter_across_tiles_enabled_flag") 142 | fmt.Printf("%-62s %-6s: %4d\n", "loop_filter_across_tiles_enabled_flag", loop_filter_across_tiles_enabled_flag_type, loop_filter_across_tiles_enabled_flag) 143 | } 144 | 145 | fmt.Printf("============================================================================\n") 146 | } 147 | -------------------------------------------------------------------------------- /hevc/helper.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | "fmt" 38 | ) 39 | 40 | type Helper struct { 41 | cmdString []string 42 | cmdLevel int 43 | cmdId int 44 | } 45 | 46 | func NewHelper(cmdString []string, cmdLevel int, cmdId int) (h *Helper){ 47 | return &Helper{cmdString, cmdLevel, cmdId} 48 | } 49 | 50 | func (h *Helper) Perform() { 51 | if h.cmdLevel == 0 { 52 | switch h.cmdString[1] { 53 | case "exit":fmt.Printf("exit: exit GoHEVC analyzer\n") 54 | case "vps": fmt.Printf("vps [n]: show num of vps [or n-th vps]\n") 55 | case "sps": fmt.Printf("sps [n]: show num of sps [or n-th sps]\n") 56 | case "pps": fmt.Printf("pps [n]: show num of pps [or the n-th pps]\n") 57 | default: fmt.Printf("frame [n]: show num of frame [or goto n-th (decoding order) frame]\n") //frame 58 | } 59 | } else if h.cmdLevel == 1 { 60 | switch h.cmdString[1] { 61 | case "exit": fmt.Printf("exit: back to up-level\n") 62 | case "tile": fmt.Printf("tile: show current frame's tile info\n") 63 | case "slice":fmt.Printf("slice [n|(x,y)]: show num of slice [or n-th slice or slice that contains pixel(x,y)]\n") 64 | case "lcu": fmt.Printf("lcu [n|(x,y)]: show num of lcu [or n-th lcu or lcu that contains pixel(x,y)]\n") 65 | default: fmt.Printf("cu [n|(x,y)]: show num of cu [or goto n-th cu or cu that contains pixel(x,y)]\n") 66 | } 67 | } else { 68 | if h.cmdId == CMD_SLICE { 69 | switch h.cmdString[1] { 70 | case "exit":fmt.Printf("exit: back to up-level\n") 71 | case "vps": fmt.Printf("vps: show current slice's vps info\n") 72 | case "sps": fmt.Printf("sps: show current slice's sps info\n") 73 | case "pps": fmt.Printf("pps: show current slice's pps info\n") 74 | default: fmt.Printf("slice: show current slice info\n") 75 | } 76 | } else if h.cmdId == CMD_LCU { 77 | switch h.cmdString[1] { 78 | case "exit": fmt.Printf("exit: back to up-level\n") 79 | case "vps": fmt.Printf("vps: show current lcu's vps info\n") 80 | case "sps": fmt.Printf("sps: show current lcu's sps info\n") 81 | case "pps": fmt.Printf("pps: show current lcu's pps info\n") 82 | case "slice":fmt.Printf("slice: show current lcu's slice info\n") 83 | default: fmt.Printf("lcu: show current lcu info\n") 84 | } 85 | } else if h.cmdId == CMD_CU { 86 | switch h.cmdString[1] { 87 | case "exit": fmt.Printf("exit: back to up-level\n") 88 | case "vps": fmt.Printf("vps: show current cu's vps info\n") 89 | case "sps": fmt.Printf("sps: show current cu's sps info\n") 90 | case "pps": fmt.Printf("pps: show current cu's pps info\n") 91 | case "slice":fmt.Printf("slice: show current cu's slice info\n") 92 | case "lcu": fmt.Printf("lcu: show current cu's lcu info\n") 93 | case "cu": fmt.Printf("cu: show current cu info\n") 94 | case "pu": fmt.Printf("pu: show current cu's pu info\n") 95 | case "tu": fmt.Printf("tu: show current cu's tu info\n") 96 | case "coef": fmt.Printf("coef: show current cu's coefficient pixels\n") 97 | case "resi": fmt.Printf("resi: show current cu's residual pixels\n") 98 | case "pred": fmt.Printf("pred: show current cu's prediction pixels\n") 99 | case "reco": fmt.Printf("reco: show current cu's reconstruction pixels\n") 100 | default: fmt.Printf("final: show current cu's final pixels\n") 101 | } 102 | } 103 | } 104 | } 105 | 106 | func (h *Helper) Parse() { 107 | switch len(h.cmdString) { 108 | case 1: 109 | if h.cmdLevel == 0 { 110 | fmt.Printf("help [exit|vps|sps|pps|frame]\n") 111 | } else if h.cmdLevel == 1 { 112 | fmt.Printf("help [exit|tile|slice|lcu|cu]\n") 113 | } else { 114 | if h.cmdId == CMD_SLICE { 115 | fmt.Printf("help [exit|vps|sps|pps|slice]\n") 116 | } else if h.cmdId == CMD_LCU { 117 | fmt.Printf("help [exit|vps|sps|pps|slice|lcu]\n") 118 | } else if h.cmdId == CMD_CU { 119 | fmt.Printf("help [exit|vps|sps|pps|slice|lcu|cu|pu|tu|coef|resi|pred|reco|final]\n") 120 | } 121 | } 122 | case 2: 123 | if h.cmdLevel == 0 { 124 | if h.cmdString[1] == "exit" || 125 | h.cmdString[1] == "vps" || 126 | h.cmdString[1] == "sps" || 127 | h.cmdString[1] == "pps" || 128 | h.cmdString[1] == "frame" { 129 | h.Perform() 130 | } else { 131 | fmt.Printf("%s: Unknown Parameters \"%s\"\n", h.cmdString[0], h.cmdString[1]) 132 | fmt.Printf("help [exit|vps|sps|pps|frame]\n") 133 | } 134 | } else if h.cmdLevel == 1 { 135 | if h.cmdString[1] == "exit" || 136 | h.cmdString[1] == "tile" || 137 | h.cmdString[1] == "slice" || 138 | h.cmdString[1] == "lcu" || 139 | h.cmdString[1] == "cu" { 140 | h.Perform() 141 | } else { 142 | fmt.Printf("%s: Unknown Parameters \"%s\"\n", h.cmdString[0], h.cmdString[1]) 143 | fmt.Printf("help [exit|tile|slice|lcu|cu]\n") 144 | } 145 | } else { 146 | if h.cmdId == CMD_SLICE { 147 | if h.cmdString[1] == "exit" || 148 | h.cmdString[1] == "vps" || 149 | h.cmdString[1] == "sps" || 150 | h.cmdString[1] == "pps" || 151 | h.cmdString[1] == "slice" { 152 | h.Perform() 153 | } else { 154 | fmt.Printf("%s: Unknown Parameters \"%s\"\n", h.cmdString[0], h.cmdString[1]) 155 | fmt.Printf("help [exit|vps|sps|pps|slice]\n") 156 | } 157 | } else if h.cmdId == CMD_LCU { 158 | if h.cmdString[1] == "exit" || 159 | h.cmdString[1] == "vps" || 160 | h.cmdString[1] == "sps" || 161 | h.cmdString[1] == "pps" || 162 | h.cmdString[1] == "slice" || 163 | h.cmdString[1] == "lcu" { 164 | h.Perform() 165 | } else { 166 | fmt.Printf("%s: Unknown Parameters \"%s\"\n", h.cmdString[0], h.cmdString[1]) 167 | fmt.Printf("help [exit|vps|sps|pps|slice|lcu]\n") 168 | } 169 | } else if h.cmdId == CMD_CU { 170 | if h.cmdString[1] == "exit" || 171 | h.cmdString[1] == "vps" || 172 | h.cmdString[1] == "sps" || 173 | h.cmdString[1] == "pps" || 174 | h.cmdString[1] == "slice" || 175 | h.cmdString[1] == "lcu" || 176 | h.cmdString[1] == "cu" || 177 | h.cmdString[1] == "pu" || 178 | h.cmdString[1] == "tu" || 179 | h.cmdString[1] == "coef" || 180 | h.cmdString[1] == "resi" || 181 | h.cmdString[1] == "pred" || 182 | h.cmdString[1] == "reco" || 183 | h.cmdString[1] == "final" { 184 | h.Perform() 185 | } else { 186 | fmt.Printf("%s: Unknown Parameters \"%s\"\n", h.cmdString[0], h.cmdString[1]) 187 | fmt.Printf("help [exit|vps|sps|pps|slice|lcu|cu|pu|tu|coef|resi|pred|reco|final]\n") 188 | } 189 | } 190 | } 191 | default: 192 | fmt.Printf("Too many parameters in \"%s\"\n", h.cmdString[0]) 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /hevc/lcu.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | //"fmt" 38 | //"errors" 39 | "bufio" 40 | "container/list" 41 | ) 42 | 43 | 44 | type LCU struct { 45 | ParameterSet 46 | CUList *list.List 47 | M_slice *Slice 48 | LcuAddr int 49 | } 50 | 51 | 52 | func NewLCU(reader *bufio.Reader) *LCU{ 53 | var lcu LCU 54 | 55 | lcu.ParameterSet.Reader = reader 56 | lcu.ParameterSet.FieldList = list.New() 57 | lcu.CUList = list.New() 58 | 59 | return &lcu 60 | } 61 | 62 | func (ps *LCU) Parse() (line string, err error) { 63 | line, err = ps.ParameterSet.Parse() 64 | 65 | ps.LcuAddr, err = ps.ParameterSet.GetValue("lcu_address") 66 | 67 | return line, err 68 | } 69 | -------------------------------------------------------------------------------- /hevc/parser.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | "bufio" 38 | "container/list" 39 | "errors" 40 | "fmt" 41 | "io" 42 | "strconv" 43 | "strings" 44 | ) 45 | 46 | const Version = 0.91 47 | 48 | const ( 49 | CMD_VPS = iota 50 | CMD_SPS 51 | CMD_PPS 52 | CMD_FRAME 53 | CMD_TILE 54 | CMD_SLICE 55 | CMD_LCU 56 | CMD_CU 57 | CMD_COEF 58 | CMD_RESI 59 | CMD_PRED 60 | CMD_RECO 61 | CMD_FINAL 62 | ) 63 | 64 | type Analyzer struct { 65 | VPSList *list.List 66 | SPSList *list.List 67 | PPSList *list.List 68 | FrameList *list.List 69 | } 70 | 71 | var CmdStr2Id map[string]int 72 | 73 | func init() { 74 | CmdStr2Id = make(map[string]int) 75 | CmdStr2Id["vps"] = CMD_VPS 76 | CmdStr2Id["sps"] = CMD_SPS 77 | CmdStr2Id["pps"] = CMD_PPS 78 | CmdStr2Id["frame"] = CMD_FRAME 79 | CmdStr2Id["tile"] = CMD_TILE 80 | CmdStr2Id["slice"] = CMD_SLICE 81 | CmdStr2Id["lcu"] = CMD_LCU 82 | CmdStr2Id["cu"] = CMD_CU 83 | CmdStr2Id["coef"] = CMD_COEF 84 | CmdStr2Id["resi"] = CMD_RESI 85 | CmdStr2Id["pred"] = CMD_PRED 86 | CmdStr2Id["reco"] = CMD_RECO 87 | CmdStr2Id["final"] = CMD_FINAL 88 | } 89 | 90 | func (ha *Analyzer) ParseTrace(traceFile io.Reader) (err error) { 91 | var line string 92 | 93 | ha.VPSList = list.New() 94 | ha.SPSList = list.New() 95 | ha.PPSList = list.New() 96 | ha.FrameList = list.New() 97 | 98 | reader := bufio.NewReader(traceFile) 99 | eof := false 100 | 101 | line, err = reader.ReadString('\n') 102 | if err == io.EOF { 103 | err = nil 104 | eof = true 105 | } else if err != nil { 106 | return err 107 | } 108 | 109 | for !eof { 110 | if strings.Contains(line, "Video Parameter Set") { 111 | vps := NewVPS(reader) 112 | if line, err = vps.Parse(); err == nil { 113 | ha.VPSList.PushBack(vps) 114 | } 115 | } else if strings.Contains(line, "Sequence Parameter Set") { 116 | sps := NewSPS(reader) 117 | if line, err = sps.Parse(); err == nil { 118 | for v := ha.VPSList.Front(); v != nil; v = v.Next() { 119 | vps := v.Value.(*VPS) 120 | if vps.VidParameterSetId == sps.VidParameterSetId { 121 | sps.M_vps = vps 122 | break 123 | } 124 | } 125 | ha.SPSList.PushBack(sps) 126 | } 127 | } else if strings.Contains(line, "Picture Parameter Set") { 128 | pps := NewPPS(reader) 129 | if line, err = pps.Parse(); err == nil { 130 | for v := ha.SPSList.Front(); v != nil; v = v.Next() { 131 | sps := v.Value.(*SPS) 132 | if sps.SeqParameterSetId == pps.SeqParameterSetId { 133 | pps.M_sps = sps 134 | break 135 | } 136 | } 137 | ha.PPSList.PushBack(pps) 138 | } 139 | } else if strings.Contains(line, "Slice Parameter Set") { 140 | slice := NewSlice(reader) 141 | if line, err = slice.Parse(); err == nil { 142 | if slice.FirstSliceInPicFlag == 1 { 143 | var poc int 144 | 145 | if poc, err = slice.GetValue("pic_order_cnt_lsb"); err != nil{ 146 | poc = 0 147 | err = nil 148 | } 149 | 150 | frame := NewFrame(poc) 151 | for v := ha.PPSList.Front(); v != nil; v = v.Next() { 152 | pps := v.Value.(*PPS) 153 | if pps.PicParameterSetId == slice.PicParameterSetId { 154 | frame.M_pps = pps 155 | break 156 | } 157 | } 158 | ha.FrameList.PushBack(frame) 159 | } 160 | frame := ha.FrameList.Back().Value.(*Frame) 161 | slice.M_frame = frame 162 | frame.SliceList.PushBack(slice) 163 | } 164 | } else if strings.Contains(line, "LCU Parameter Set") { 165 | fmt.Printf(".") 166 | 167 | lcu := NewLCU(reader) 168 | if line, err = lcu.Parse(); err == nil { 169 | frame := ha.FrameList.Back().Value.(*Frame) 170 | slice := frame.SliceList.Back().Value.(*Slice) 171 | lcu.M_slice = slice 172 | frame.LCUList.PushBack(lcu) 173 | } 174 | } else if strings.Contains(line, "CU Parameter Set") { 175 | cu := NewCU(reader) 176 | if line, err = cu.Parse(); err == nil { 177 | frame := ha.FrameList.Back().Value.(*Frame) 178 | lcu := frame.LCUList.Back().Value.(*LCU) 179 | cu.M_lcu = lcu 180 | lcu.CUList.PushBack(cu) 181 | } 182 | } else if strings.Contains(line, "PU Parameter Set") { 183 | pu := NewPU(reader) 184 | if line, err = pu.Parse(); err == nil { 185 | frame := ha.FrameList.Back().Value.(*Frame) 186 | lcu := frame.LCUList.Back().Value.(*LCU) 187 | cu := lcu.CUList.Back().Value.(*CU) 188 | pu.M_cu = cu 189 | cu.PUList.PushBack(pu) 190 | } 191 | } else if strings.Contains(line, "TU Parameter Set") { 192 | tu := NewTU(reader) 193 | if line, err = tu.Parse(); err == nil { 194 | frame := ha.FrameList.Back().Value.(*Frame) 195 | lcu := frame.LCUList.Back().Value.(*LCU) 196 | cu := lcu.CUList.Back().Value.(*CU) 197 | tu.M_cu = cu 198 | cu.TUList.PushBack(tu) 199 | } 200 | } else if strings.Contains(line, "Coefficient Parameter Set") { 201 | frame := ha.FrameList.Back().Value.(*Frame) 202 | lcu := frame.LCUList.Back().Value.(*LCU) 203 | cu := lcu.CUList.Back().Value.(*CU) 204 | tu := cu.TUList.Back().Value.(*TU) 205 | coef := NewDATA(reader, tu.Tu_color, tu.Tu_x, tu.Tu_y, tu.Tu_width, tu.Tu_height, TCOEF) 206 | if line, err = coef.Parse(); err == nil { 207 | //coef.M_tu = tu 208 | tu.CoefList.PushBack(coef) 209 | } 210 | } else if strings.Contains(line, "Residual Parameter Set") { 211 | frame := ha.FrameList.Back().Value.(*Frame) 212 | lcu := frame.LCUList.Back().Value.(*LCU) 213 | cu := lcu.CUList.Back().Value.(*CU) 214 | tu := cu.TUList.Back().Value.(*TU) 215 | resi := NewDATA(reader, tu.Tu_color, tu.Tu_x, tu.Tu_y, tu.Tu_width, tu.Tu_height, TPEL) 216 | if line, err = resi.Parse(); err == nil { 217 | //resi.M_tu = tu 218 | tu.ResiList.PushBack(resi) 219 | } 220 | } else if strings.Contains(line, "Prediction Parameter Set") { 221 | frame := ha.FrameList.Back().Value.(*Frame) 222 | lcu := frame.LCUList.Back().Value.(*LCU) 223 | cu := lcu.CUList.Back().Value.(*CU) 224 | tu := cu.TUList.Back().Value.(*TU) 225 | pred := NewDATA(reader, tu.Tu_color, tu.Tu_x, tu.Tu_y, tu.Tu_width, tu.Tu_height, TPXL) 226 | if line, err = pred.Parse(); err == nil { 227 | //pred.M_tu = tu 228 | tu.PredList.PushBack(pred) 229 | } 230 | } else if strings.Contains(line, "Reconstruction Parameter Set") { 231 | frame := ha.FrameList.Back().Value.(*Frame) 232 | lcu := frame.LCUList.Back().Value.(*LCU) 233 | cu := lcu.CUList.Back().Value.(*CU) 234 | tu := cu.TUList.Back().Value.(*TU) 235 | reco := NewDATA(reader, tu.Tu_color, tu.Tu_x, tu.Tu_y, tu.Tu_width, tu.Tu_height, TPXL) 236 | if line, err = reco.Parse(); err == nil { 237 | //reco.M_tu = tu 238 | tu.RecoList.PushBack(reco) 239 | } 240 | } else if strings.TrimSpace(line) == "" { 241 | eof = true 242 | fmt.Printf("\n") 243 | } else { 244 | eof = true 245 | err = errors.New("Unknown Parameter Set\n") 246 | } 247 | 248 | if err == io.EOF { 249 | err = nil 250 | eof = true 251 | } else if err != nil { 252 | eof = true 253 | } 254 | } 255 | 256 | return err 257 | } 258 | 259 | func (ha *Analyzer) ParseYUV(yuvFile io.Reader) (err error) { 260 | err = nil 261 | reader := bufio.NewReader(yuvFile) 262 | 263 | for i:=0; i", prefix) 322 | line, err := reader.ReadString('\n') 323 | if err != nil { 324 | break 325 | } 326 | 327 | cmdString := strings.Fields(strings.TrimSpace(line)) 328 | 329 | if len(cmdString) == 0 { 330 | continue 331 | } else if cmdString[0] == "exit" { 332 | break 333 | } else if cmdString[0] == "help" { 334 | NewHelper(cmdString, cmdLevel, cmdId).Parse() 335 | } else if cmdString[0] == "vps" || 336 | cmdString[0] == "sps" || 337 | cmdString[0] == "pps" { 338 | if len(cmdString) == 1 { 339 | if cmdString[0] == "vps" { 340 | fmt.Printf("Total Number of %s: %d\n", cmdString[0], ha.VPSList.Len()) 341 | } else if cmdString[0] == "sps" { 342 | fmt.Printf("Total Number of %s: %d\n", cmdString[0], ha.SPSList.Len()) 343 | } else { //cmdString[0] == "pps" 344 | fmt.Printf("Total Number of %s: %d\n", cmdString[0], ha.PPSList.Len()) 345 | } 346 | } else if len(cmdString) == 2 { 347 | if n, err := strconv.ParseInt(cmdString[1], 0, 0); err != nil { 348 | fmt.Printf("%s: Invalid Parameters \"%s\"\n", cmdString[0], cmdString[1]) 349 | } else { 350 | if cmdString[0] == "vps" { 351 | if int(n) < ha.VPSList.Len() { 352 | for v := ha.VPSList.Front(); v != nil; v = v.Next() { 353 | vps := v.Value.(*VPS) 354 | if vps.VidParameterSetId == int(n) { 355 | vps.ShowInfo() 356 | break 357 | } 358 | } 359 | } else { 360 | fmt.Printf("Warning: can't find %d-th %s\n", n, cmdString[0]) 361 | } 362 | } else if cmdString[0] == "sps" { 363 | if int(n) < ha.SPSList.Len() { 364 | for v := ha.SPSList.Front(); v != nil; v = v.Next() { 365 | sps := v.Value.(*SPS) 366 | if sps.SeqParameterSetId == int(n) { 367 | sps.ShowInfo() 368 | break 369 | } 370 | } 371 | } else { 372 | fmt.Printf("Warning: can't find %d-th %s\n", n, cmdString[0]) 373 | } 374 | } else { //cmdString[0] == "pps" 375 | if int(n) < ha.PPSList.Len() { 376 | for v := ha.PPSList.Front(); v != nil; v = v.Next() { 377 | pps := v.Value.(*PPS) 378 | if pps.PicParameterSetId == int(n) { 379 | pps.ShowInfo() 380 | break 381 | } 382 | } 383 | } else { 384 | fmt.Printf("Warning: can't find %d-th %s\n", n, cmdString[0]) 385 | } 386 | } 387 | } 388 | } else { 389 | fmt.Printf("Too many parameters in command \"%s\"\n", cmdString[0]) 390 | } 391 | } else if cmdString[0] == "frame" { 392 | if len(cmdString) == 1 { 393 | fmt.Printf("Total Number of %s: %d", cmdString[0], ha.FrameList.Len()) 394 | fmt.Printf("%s\n", out) 395 | } else if len(cmdString) == 2 { 396 | if n, err := strconv.ParseInt(cmdString[1], 0, 0); err != nil { 397 | fmt.Printf("%s: Invalid Parameters \"%s\"\n", cmdString[0], cmdString[1]) 398 | } else { 399 | if int(n) < ha.FrameList.Len() { 400 | for v := ha.FrameList.Front(); v != nil; v = v.Next() { 401 | frame := v.Value.(*Frame) 402 | if frame.FrameId == int(n) { 403 | ParseCmdFrame(prefix+"\\"+cmdString[0]+" "+cmdString[1], reader, cmdLevel+1, CmdStr2Id[cmdString[0]], frame) 404 | break 405 | } 406 | } 407 | } else { 408 | fmt.Printf("Warning: can't find %d-th %s\n", n, cmdString[0]) 409 | } 410 | } 411 | } else { 412 | fmt.Printf("Too many parameters in command \"%s\"\n", cmdString[0]) 413 | } 414 | } else { 415 | fmt.Printf("Unknown Command \"%s\"\n", cmdString[0]) 416 | } 417 | } 418 | } 419 | 420 | func ParseCmdFrame(prefix string, reader *bufio.Reader, cmdLevel int, cmdId int, frame *Frame) { 421 | for { 422 | fmt.Printf("%s>", prefix) 423 | line, err := reader.ReadString('\n') 424 | if err != nil { 425 | break 426 | } 427 | 428 | cmdString := strings.Fields(strings.TrimSpace(line)) 429 | 430 | if len(cmdString) == 0 { 431 | continue 432 | } else if cmdString[0] == "exit" { 433 | break 434 | } else if cmdString[0] == "help" { 435 | NewHelper(cmdString, cmdLevel, cmdId).Parse() 436 | } else if cmdString[0] == "tile" { 437 | if len(cmdString) == 1 { 438 | frame.ShowTileSummary() 439 | } else { 440 | fmt.Printf("Too many parameters in command \"%s\"\n", cmdString[0]) 441 | } 442 | } else if cmdString[0] == "slice" || 443 | cmdString[0] == "lcu" || 444 | cmdString[0] == "cu" { 445 | if len(cmdString) == 1 { 446 | if cmdString[0] == "slice" { 447 | fmt.Printf("Total Number of %s: %d\n", cmdString[0], frame.SliceList.Len()) 448 | }else if cmdString[0] == "lcu" { 449 | fmt.Printf("Total Number of %s: %d\n", cmdString[0], frame.LCUList.Len()) //frame.M_pps.M_sps.WidthInLcu*frame.M_pps.M_sps.HeightInLcu) 450 | }else{//"cu" 451 | n := 0; 452 | for v := frame.LCUList.Front(); v != nil; v = v.Next() { 453 | lcu := v.Value.(*LCU) 454 | n = n + lcu.CUList.Len(); 455 | } 456 | fmt.Printf("Total Number of %s: %d\n", cmdString[0], n) 457 | } 458 | } else if len(cmdString) == 2 { 459 | if cmdString[0]=="slice" { 460 | if strings.HasPrefix(cmdString[1], "(") && strings.HasSuffix(cmdString[1], ")") { 461 | xy := strings.Split(strings.TrimRight(strings.TrimLeft(cmdString[1], "("), ")"), ","); 462 | x, err1:= strconv.ParseInt(strings.TrimSpace(xy[0]), 0, 0) 463 | y, err2:= strconv.ParseInt(strings.TrimSpace(xy[1]), 0, 0) 464 | if err1 !=nil || err2 !=nil || int(x) < 0 || int(x) >= frame.M_pps.M_sps.FrameWidth || int(y) < 0 || int(y) >= frame.M_pps.M_sps.FrameHeight{ 465 | fmt.Printf("%s: Invalid Parameters \"%s\"\n", cmdString[0], cmdString[1]) 466 | }else{ 467 | xInLcu, yInLcu := int(x)/frame.M_pps.M_sps.LcuSize, int(y)/frame.M_pps.M_sps.LcuSize 468 | LcuAddr := yInLcu*frame.M_pps.M_sps.WidthInLcu+xInLcu; 469 | for v := frame.LCUList.Front(); v != nil; v = v.Next() { 470 | lcu := v.Value.(*LCU) 471 | if LcuAddr == lcu.LcuAddr { 472 | slice := lcu.M_slice 473 | ParseCmdSliceLcuCu(prefix+"\\"+cmdString[0]+" "+strconv.Itoa(LcuAddr), reader, cmdLevel+1, CmdStr2Id[cmdString[0]], slice) 474 | break 475 | } 476 | } 477 | } 478 | } else if n, err := strconv.ParseInt(cmdString[1], 0, 0); err != nil { 479 | fmt.Printf("%s: Invalid Parameters \"%s\"\n", cmdString[0], cmdString[1]) 480 | } else { 481 | if int(n) < frame.SliceList.Len() { 482 | for v, i := frame.SliceList.Front(), 0; v != nil; v, i = v.Next(), i+1 { 483 | if i == int(n) { 484 | slice := v.Value.(*Slice) 485 | ParseCmdSliceLcuCu(prefix+"\\"+cmdString[0]+" "+cmdString[1], reader, cmdLevel+1, CmdStr2Id[cmdString[0]], slice) 486 | break 487 | } 488 | } 489 | } else { 490 | fmt.Printf("Warning: can't find %d-th %s\n", n, cmdString[0]) 491 | } 492 | } 493 | }else if cmdString[0]=="lcu" { 494 | if strings.HasPrefix(cmdString[1], "(") && strings.HasSuffix(cmdString[1], ")") { 495 | xy := strings.Split(strings.TrimRight(strings.TrimLeft(cmdString[1], "("), ")"), ","); 496 | x, err1:= strconv.ParseInt(strings.TrimSpace(xy[0]), 0, 0) 497 | y, err2:= strconv.ParseInt(strings.TrimSpace(xy[1]), 0, 0) 498 | if err1 !=nil || err2 !=nil || int(x) < 0 || int(x) >= frame.M_pps.M_sps.FrameWidth || int(y) < 0 || int(y) >= frame.M_pps.M_sps.FrameHeight{ 499 | fmt.Printf("%s: Invalid Parameters \"%s\"\n", cmdString[0], cmdString[1]) 500 | }else{ 501 | xInLcu, yInLcu := int(x)/frame.M_pps.M_sps.LcuSize, int(y)/frame.M_pps.M_sps.LcuSize 502 | LcuAddr := yInLcu*frame.M_pps.M_sps.WidthInLcu+xInLcu; 503 | for v := frame.LCUList.Front(); v != nil; v = v.Next() { 504 | lcu := v.Value.(*LCU) 505 | if LcuAddr == lcu.LcuAddr { 506 | ParseCmdSliceLcuCu(prefix+"\\"+cmdString[0]+" "+strconv.Itoa(LcuAddr), reader, cmdLevel+1, CmdStr2Id[cmdString[0]], lcu) 507 | break 508 | } 509 | } 510 | } 511 | } else if n, err := strconv.ParseInt(cmdString[1], 0, 0); err != nil { 512 | fmt.Printf("%s: Invalid Parameters \"%s\"\n", cmdString[0], cmdString[1]) 513 | } else { 514 | if int(n) < frame.LCUList.Len() { 515 | for v := frame.LCUList.Front(); v != nil; v = v.Next() { 516 | lcu := v.Value.(*LCU) 517 | if int(n) == lcu.LcuAddr { 518 | ParseCmdSliceLcuCu(prefix+"\\"+cmdString[0]+" "+cmdString[1], reader, cmdLevel+1, CmdStr2Id[cmdString[0]], lcu) 519 | break 520 | } 521 | } 522 | } else { 523 | fmt.Printf("Warning: can't find %d-th %s\n", n, cmdString[0]) 524 | } 525 | } 526 | }else{//"cu" 527 | if strings.HasPrefix(cmdString[1], "(") && strings.HasSuffix(cmdString[1], ")") { 528 | xy := strings.Split(strings.TrimRight(strings.TrimLeft(cmdString[1], "("), ")"), ","); 529 | x, err1:= strconv.ParseInt(strings.TrimSpace(xy[0]), 0, 0) 530 | y, err2:= strconv.ParseInt(strings.TrimSpace(xy[1]), 0, 0) 531 | if err1 !=nil || err2 !=nil || int(x) < 0 || int(x) >= frame.M_pps.M_sps.FrameWidth || int(y) < 0 || int(y) >= frame.M_pps.M_sps.FrameHeight{ 532 | fmt.Printf("%s: Invalid Parameters \"%s\"\n", cmdString[0], cmdString[1]) 533 | }else{ 534 | xInCu, yInCu := int(x), int(y) 535 | xInLcu, yInLcu := xInCu/frame.M_pps.M_sps.LcuSize, yInCu/frame.M_pps.M_sps.LcuSize 536 | LcuAddr := yInLcu*frame.M_pps.M_sps.WidthInLcu+xInLcu; 537 | for v := frame.LCUList.Front(); v != nil; v = v.Next() { 538 | lcu := v.Value.(*LCU) 539 | if LcuAddr == lcu.LcuAddr { 540 | for e := lcu.CUList.Front(); e != nil; e = e.Next() { 541 | cu := e.Value.(*CU) 542 | if xInCu >= cu.Cu_x && xInCu < cu.Cu_x+cu.Cu_size && 543 | yInCu >= cu.Cu_y && yInCu < cu.Cu_y+cu.Cu_size { 544 | ParseCmdSliceLcuCu(prefix+"\\"+cmdString[0]+" ("+strconv.Itoa(cu.Cu_x)+","+strconv.Itoa(cu.Cu_y)+")", reader, cmdLevel+1, CmdStr2Id[cmdString[0]], cu) 545 | break 546 | } 547 | } 548 | break 549 | } 550 | } 551 | } 552 | } else if n, err := strconv.ParseInt(cmdString[1], 0, 0); err != nil { 553 | fmt.Printf("%s: Invalid Parameters \"%s\"\n", cmdString[0], cmdString[1]) 554 | } else { 555 | nInCu := 0; 556 | for v := frame.LCUList.Front(); v != nil; v = v.Next() { 557 | lcu := v.Value.(*LCU) 558 | if int(n) >= nInCu && int(n) < nInCu+lcu.CUList.Len(){ 559 | for e := lcu.CUList.Front(); e != nil; e = e.Next() { 560 | if int(n) == nInCu { 561 | cu := e.Value.(*CU) 562 | ParseCmdSliceLcuCu(prefix+"\\"+cmdString[0]+" "+cmdString[1], reader, cmdLevel+1, CmdStr2Id[cmdString[0]], cu) 563 | break 564 | }else{ 565 | nInCu = nInCu + 1 566 | } 567 | } 568 | break 569 | }else{ 570 | nInCu = nInCu + lcu.CUList.Len(); 571 | } 572 | } 573 | 574 | if int(n) != nInCu { 575 | fmt.Printf("Warning: can't find %d-th %s\n", n, cmdString[0]) 576 | } 577 | } 578 | } 579 | } else { 580 | fmt.Printf("Too many parameters in command \"%s\"\n", cmdString[0]) 581 | } 582 | } else { 583 | fmt.Printf("Unknown command \"%s\"\n", cmdString[0]) 584 | } 585 | } 586 | } 587 | 588 | func ParseCmdSliceLcuCu(prefix string, reader *bufio.Reader, cmdLevel int, cmdId int, slc interface{}) { 589 | for { 590 | fmt.Printf("%s>", prefix) 591 | line, err := reader.ReadString('\n') 592 | if err != nil { 593 | break 594 | } 595 | 596 | cmdString := strings.Fields(strings.TrimSpace(line)) 597 | 598 | if len(cmdString) == 0 { 599 | continue 600 | } else if cmdString[0] == "exit" { 601 | break 602 | } else if cmdString[0] == "help" { 603 | NewHelper(cmdString, cmdLevel, cmdId).Parse() 604 | } else if cmdString[0] == "vps" || 605 | cmdString[0] == "sps" || 606 | cmdString[0] == "pps" || 607 | cmdString[0] == "slice" { 608 | var slice *Slice 609 | switch slc.(type) { 610 | case *Slice: slice = slc.(*Slice) 611 | case *LCU: slice = slc.(*LCU).M_slice 612 | case *CU: slice = slc.(*CU).M_lcu.M_slice 613 | default: break 614 | } 615 | if len(cmdString) == 1 { 616 | if cmdString[0] == "slice" { 617 | slice.ShowInfo() 618 | }else if cmdString[0] == "pps" { 619 | slice.M_frame.M_pps.ShowInfo() 620 | }else if cmdString[0] == "sps" { 621 | slice.M_frame.M_pps.M_sps.ShowInfo() 622 | }else{//vps 623 | slice.M_frame.M_pps.M_sps.M_vps.ShowInfo() 624 | } 625 | } else { 626 | fmt.Printf("Too many parameters in command \"%s\"\n", cmdString[0]) 627 | } 628 | } else if cmdString[0] == "lcu" && (cmdId == CMD_LCU ||cmdId==CMD_CU) { 629 | var lcu *LCU 630 | switch slc.(type) { 631 | case *LCU: lcu = slc.(*LCU) 632 | case *CU: lcu = slc.(*CU).M_lcu 633 | default: break 634 | } 635 | if len(cmdString) == 1 { 636 | lcu.ShowInfo() 637 | } else { 638 | fmt.Printf("Too many parameters in command \"%s\"\n", cmdString[0]) 639 | } 640 | } else if (cmdString[0] == "cu" || 641 | cmdString[0] == "pu" || 642 | cmdString[0] == "tu" || 643 | cmdString[0] == "coef" || 644 | cmdString[0] == "resi" || 645 | cmdString[0] == "pred" || 646 | cmdString[0] == "reco" || 647 | cmdString[0] == "final") && 648 | cmdId == CMD_CU { 649 | cu := slc.(*CU) 650 | if len(cmdString) == 1 { 651 | if cmdString[0] == "cu" { 652 | cu.ShowInfo() 653 | }else if cmdString[0] == "pu" { 654 | for e := cu.PUList.Front(); e != nil; e = e.Next() { 655 | pu := e.Value.(*PU) 656 | pu.ShowInfo() 657 | } 658 | }else if cmdString[0] == "tu" { 659 | for e := cu.TUList.Front(); e != nil; e = e.Next() { 660 | tu := e.Value.(*TU) 661 | tu.ShowInfo() 662 | } 663 | }else if cmdString[0] == "coef" { 664 | for e := cu.TUList.Front(); e != nil; e = e.Next() { 665 | tu := e.Value.(*TU) 666 | for v := tu.CoefList.Front(); v != nil; v = v.Next() { 667 | coef := v.Value.(*DATA) 668 | coef.ShowInfo() 669 | } 670 | } 671 | }else if cmdString[0] == "resi" { 672 | for e := cu.TUList.Front(); e != nil; e = e.Next() { 673 | tu := e.Value.(*TU) 674 | for v := tu.ResiList.Front(); v != nil; v = v.Next() { 675 | resi := v.Value.(*DATA) 676 | resi.ShowInfo() 677 | } 678 | } 679 | }else if cmdString[0] == "pred" { 680 | for e := cu.TUList.Front(); e != nil; e = e.Next() { 681 | tu := e.Value.(*TU) 682 | for v := tu.PredList.Front(); v != nil; v = v.Next() { 683 | pred := v.Value.(*DATA) 684 | pred.ShowInfo() 685 | } 686 | } 687 | }else if cmdString[0] == "reco" { 688 | for e := cu.TUList.Front(); e != nil; e = e.Next() { 689 | tu := e.Value.(*TU) 690 | for v := tu.RecoList.Front(); v != nil; v = v.Next() { 691 | reco := v.Value.(*DATA) 692 | reco.ShowInfo() 693 | } 694 | } 695 | }else{ 696 | for e := cu.TUList.Front(); e != nil; e = e.Next() { 697 | tu := e.Value.(*TU) 698 | for v := tu.FinalList.Front(); v != nil; v = v.Next() { 699 | final := v.Value.(*DATA) 700 | final.ShowInfo() 701 | } 702 | } 703 | //fmt.Printf("Perform command: \"%s\"\n", cmdString[0]) 704 | } 705 | } else { 706 | fmt.Printf("Too many parameters in command \"%s\"\n", cmdString[0]) 707 | } 708 | } else { 709 | fmt.Printf("Unknown command \"%s\"\n", cmdString[0]) 710 | } 711 | } 712 | } 713 | -------------------------------------------------------------------------------- /hevc/pps.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | //"fmt" 38 | "errors" 39 | "bufio" 40 | "container/list" 41 | ) 42 | 43 | type PPS struct { 44 | ParameterSet 45 | M_sps *SPS 46 | SeqParameterSetId int 47 | PicParameterSetId int 48 | } 49 | 50 | func NewPPS(reader *bufio.Reader) *PPS{ 51 | var pps PPS 52 | 53 | pps.ParameterSet.Reader = reader 54 | pps.ParameterSet.FieldList = list.New() 55 | 56 | return &pps 57 | } 58 | 59 | func (ps *PPS) Parse() (line string, err error) { 60 | line, err = ps.ParameterSet.Parse() 61 | 62 | ps.SeqParameterSetId = -1 63 | ps.PicParameterSetId = -1 64 | for e := ps.FieldList.Front(); e != nil; e = e.Next() { 65 | field := e.Value.(Field) 66 | 67 | if field.Name == "seq_parameter_set_id" { 68 | ps.SeqParameterSetId = field.Value 69 | }else if field.Name == "pic_parameter_set_id" { 70 | ps.PicParameterSetId = field.Value 71 | } 72 | } 73 | 74 | if ps.PicParameterSetId < 0 || 75 | ps.SeqParameterSetId < 0 { 76 | err = errors.New("pic_parameter_set_id or seq_parameter_set_id not found or invalid") 77 | } 78 | 79 | return 80 | } 81 | -------------------------------------------------------------------------------- /hevc/ps.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | "errors" 38 | "fmt" 39 | "io" 40 | "bufio" 41 | "strings" 42 | "strconv" 43 | "container/list" 44 | ) 45 | 46 | const POS_NAME = 0 47 | const POS_TYPE = 1 48 | const POS_VALUE = 3 49 | 50 | type Field struct { 51 | Name string 52 | Type string 53 | Value int 54 | } 55 | 56 | type ParameterSet struct { 57 | Reader *bufio.Reader 58 | FieldList *list.List 59 | } 60 | 61 | func (ps *ParameterSet) Parse() (line string, err error) { 62 | if ps.Reader==nil{ 63 | line = "" 64 | err = errors.New("nil Reader\n") 65 | return line, err 66 | } 67 | 68 | eof := false 69 | for !eof { 70 | line, err = ps.Reader.ReadString('\n') 71 | if err == io.EOF { 72 | err = nil 73 | eof = true 74 | }else if err != nil { 75 | return line, err 76 | }else if strings.HasPrefix(line, "=========") { 77 | return line, err 78 | }else{ 79 | var value int64 80 | var field Field 81 | fieldstr := strings.Fields(strings.TrimSpace(line)) 82 | field.Name = fieldstr[POS_NAME] 83 | field.Type = fieldstr[POS_TYPE] 84 | value, err = strconv.ParseInt(fieldstr[POS_VALUE], 0, 0) 85 | if err != nil { 86 | return line, err 87 | }else{ 88 | field.Value = int(value) 89 | ps.FieldList.PushBack(field) 90 | } 91 | } 92 | } 93 | 94 | return 95 | } 96 | 97 | func (ps *ParameterSet) GetValue(name string) (value int, err error){ 98 | err = errors.New(name+" not found\n") 99 | for e := ps.FieldList.Front(); e != nil; e = e.Next() { 100 | field := e.Value.(Field) 101 | 102 | if field.Name == name { 103 | value, err = field.Value, nil 104 | break 105 | } 106 | } 107 | 108 | return value, err 109 | } 110 | 111 | 112 | func (ps *ParameterSet) GetTypeValue(name string) (t string, v int, err error){ 113 | err = errors.New(name+" not found\n") 114 | for e := ps.FieldList.Front(); e != nil; e = e.Next() { 115 | field := e.Value.(Field) 116 | 117 | if field.Name == name { 118 | t, v, err = field.Type, field.Value, nil 119 | break 120 | } 121 | } 122 | 123 | return t, v, err 124 | } 125 | 126 | 127 | func (ps *ParameterSet) ShowInfo(){ 128 | fmt.Printf("===========================================================================\n",) 129 | for e := ps.FieldList.Front(); e != nil; e = e.Next() { 130 | field := e.Value.(Field) 131 | fmt.Printf("%-62s %-6s: %4d\n", field.Name, field.Type, field.Value) 132 | } 133 | //fmt.Printf("===========================================================================\n") 134 | } 135 | -------------------------------------------------------------------------------- /hevc/pu.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | //"fmt" 38 | //"errors" 39 | "bufio" 40 | "container/list" 41 | ) 42 | 43 | 44 | type PU struct { 45 | ParameterSet 46 | M_cu *CU 47 | } 48 | 49 | 50 | func NewPU(reader *bufio.Reader) *PU{ 51 | var pu PU 52 | 53 | pu.ParameterSet.Reader = reader 54 | pu.ParameterSet.FieldList = list.New() 55 | 56 | return &pu 57 | } 58 | 59 | func (ps *PU) Parse() (line string, err error) { 60 | line, err = ps.ParameterSet.Parse() 61 | 62 | return line, err 63 | } 64 | 65 | -------------------------------------------------------------------------------- /hevc/slice.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | //"fmt" 38 | "errors" 39 | "bufio" 40 | "container/list" 41 | ) 42 | 43 | type Slice struct { 44 | ParameterSet 45 | M_frame *Frame 46 | PicParameterSetId int 47 | FirstSliceInPicFlag int 48 | SliceAddr int 49 | } 50 | 51 | func NewSlice(reader *bufio.Reader) *Slice{ 52 | var slice Slice 53 | 54 | slice.ParameterSet.Reader = reader 55 | slice.ParameterSet.FieldList = list.New() 56 | 57 | return &slice 58 | } 59 | 60 | func (ps *Slice) Parse() (line string, err error) { 61 | line, err = ps.ParameterSet.Parse() 62 | 63 | ps.PicParameterSetId = -1 64 | ps.FirstSliceInPicFlag = 0 65 | for e := ps.FieldList.Front(); e != nil; e = e.Next() { 66 | field := e.Value.(Field) 67 | 68 | if field.Name == "pic_parameter_set_id" { 69 | ps.PicParameterSetId = field.Value 70 | }else if field.Name == "first_slice_in_pic_flag" { 71 | ps.FirstSliceInPicFlag = field.Value 72 | } 73 | } 74 | 75 | if ps.PicParameterSetId < 0 { 76 | err = errors.New("pic_parameter_set_id not found or invalid") 77 | } 78 | 79 | if ps.FirstSliceInPicFlag==1{ 80 | ps.SliceAddr = 0 81 | }else{ 82 | ps.SliceAddr, err = ps.ParameterSet.GetValue("slice_address") 83 | } 84 | 85 | return line, err 86 | } 87 | -------------------------------------------------------------------------------- /hevc/sps.go: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2012-2013, H265.net 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the H265.net nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package hevc 35 | 36 | import ( 37 | //"fmt" 38 | "errors" 39 | "bufio" 40 | "container/list" 41 | ) 42 | 43 | type SPS struct { 44 | ParameterSet 45 | M_vps *VPS 46 | VidParameterSetId int 47 | SeqParameterSetId int 48 | 49 | FrameWidth int 50 | FrameHeight int 51 | LcuSize int 52 | WidthInLcu int 53 | HeightInLcu int 54 | } 55 | 56 | func NewSPS(reader *bufio.Reader) *SPS{ 57 | var sps SPS 58 | 59 | sps.ParameterSet.Reader = reader 60 | sps.ParameterSet.FieldList = list.New() 61 | 62 | return &sps 63 | } 64 | 65 | func (ps *SPS) Parse() (line string, err error) { 66 | line, err = ps.ParameterSet.Parse() 67 | 68 | ps.VidParameterSetId = -1 69 | ps.SeqParameterSetId = -1 70 | for e := ps.FieldList.Front(); e != nil; e = e.Next() { 71 | field := e.Value.(Field) 72 | 73 | if field.Name == "video_parameter_set_id" { 74 | ps.VidParameterSetId = field.Value 75 | }else if field.Name == "seq_parameter_set_id" { 76 | ps.SeqParameterSetId = field.Value 77 | } 78 | } 79 | 80 | if ps.VidParameterSetId < 0 || 81 | ps.SeqParameterSetId < 0 { 82 | err = errors.New("video_parameter_set_id or seq_parameter_set_id not found or invalid") 83 | } 84 | 85 | ps.FrameWidth, err = ps.ParameterSet.GetValue("pic_width_in_luma_samples") 86 | ps.FrameHeight, err = ps.ParameterSet.GetValue("pic_height_in_luma_samples") 87 | 88 | var log2_min_coding_block_size_minus3, log2_diff_max_min_coding_block_size int 89 | log2_min_coding_block_size_minus3, err = ps.ParameterSet.GetValue("log2_min_coding_block_size_minus3") 90 | log2_diff_max_min_coding_block_size,err = ps.ParameterSet.GetValue("log2_diff_max_min_coding_block_size") 91 | ps.LcuSize = 1<