Skip to content

Commit 4aaca4b

Browse files
committed
hello, erasepinf
0 parents  commit 4aaca4b

File tree

3 files changed

+190
-0
lines changed

3 files changed

+190
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea/

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# erasepinf
2+
pinf eraser
3+
4+
```sh
5+
./erasepinf <mp4 filename>
6+
```
7+
8+
9+
## License
10+
MIT

erasepinf.go

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"os"
6+
"encoding/binary"
7+
"encoding/hex"
8+
"io"
9+
"errors"
10+
"fmt"
11+
)
12+
13+
// atomName => padding size
14+
var boxAtomPaddings = map[string]int64{
15+
"moov": 0,
16+
"trak": 0,
17+
"mdia": 0,
18+
"minf": 0,
19+
"stsd": 8,
20+
"stbl": 0,
21+
"mp4a": 28,
22+
23+
// --- in pinf
24+
"pinf": 0,
25+
"schi": 0,
26+
}
27+
28+
func main() {
29+
if len(os.Args) < 2 {
30+
log.Fatalf("Usage: ./erasepinf <mp4 filename>")
31+
}
32+
33+
filename := os.Args[1]
34+
f, err := os.OpenFile(filename, os.O_RDWR, 0644)
35+
defer f.Close()
36+
if err != nil {
37+
log.Fatalln(err)
38+
}
39+
40+
atoms, err := readAllAtoms(f)
41+
if err != nil {
42+
log.Fatalln(err)
43+
}
44+
45+
pinf, err := searchAtom(atoms, "pinf")
46+
if err != nil {
47+
log.Fatalln(err)
48+
}
49+
50+
dumper := hex.Dumper(os.Stdout)
51+
defer dumper.Close()
52+
53+
data, err := pinf.ReadData(f)
54+
if err != nil {
55+
log.Fatalln(err)
56+
}
57+
58+
fmt.Println("-------------before-----------------")
59+
dumper.Write(data)
60+
61+
if err := pinf.destroy(f); err != nil {
62+
log.Fatalln(err)
63+
}
64+
65+
data, err = pinf.ReadData(f)
66+
if err != nil {
67+
log.Fatalln(err)
68+
}
69+
70+
fmt.Println("-------------after-----------------")
71+
dumper.Write(data)
72+
}
73+
74+
func searchAtom(atoms map[string]*Atom, target string) (*Atom, error) {
75+
for name, atom := range atoms {
76+
if name == target {
77+
return atom, nil
78+
}
79+
if len(atom.Children) > 0 {
80+
return searchAtom(atom.Children, target)
81+
}
82+
}
83+
return nil, errors.New("not found")
84+
}
85+
86+
type Atom struct {
87+
Name string
88+
DataStartPos int64
89+
DataLen int64
90+
Children map[string]*Atom
91+
}
92+
93+
func (a *Atom) ReadData(r io.ReadSeeker) ([]byte, error) {
94+
if _, err := r.Seek(a.DataStartPos, io.SeekStart); err != nil {
95+
return nil, err
96+
}
97+
buf := make([]byte, a.DataLen)
98+
if _, err := io.ReadFull(r, buf); err != nil {
99+
return nil, err
100+
}
101+
return buf, nil
102+
}
103+
104+
func (a *Atom) destroy(w io.WriteSeeker) (error) {
105+
if _, err := w.Seek(a.DataStartPos, io.SeekStart); err != nil {
106+
return err
107+
}
108+
pad := make([]byte, a.DataLen)
109+
if _, err := w.Write(pad); err != nil {
110+
return err
111+
}
112+
return nil
113+
}
114+
115+
func readAllAtoms(r io.ReadSeeker) (map[string]*Atom, error) {
116+
atoms := make(map[string]*Atom)
117+
for {
118+
atom, err := readAtom(r)
119+
if err != nil {
120+
if err != io.EOF {
121+
return nil, err
122+
}
123+
break
124+
}
125+
atoms[atom.Name] = atom
126+
}
127+
return atoms, nil
128+
}
129+
130+
func readAtom(r io.ReadSeeker) (*Atom, error) {
131+
var length uint32
132+
if err := binary.Read(r, binary.BigEndian, &length); err != nil {
133+
return nil, err
134+
}
135+
136+
nameb := make([]byte, 4)
137+
if err := binary.Read(r, binary.BigEndian, &nameb); err != nil {
138+
return nil, err
139+
}
140+
name := string(nameb)
141+
142+
startPos, err := r.Seek(0, io.SeekCurrent)
143+
if err != nil {
144+
return nil, err
145+
}
146+
dataLen := int64(length - 8)
147+
148+
catoms := make(map[string]*Atom)
149+
pad, isBox := boxAtomPaddings[name]
150+
if isBox {
151+
r.Seek(pad, io.SeekCurrent)
152+
for {
153+
catom, err := readAtom(r)
154+
if err != nil {
155+
return nil, err
156+
}
157+
catoms[catom.Name] = catom
158+
159+
cur, err := r.Seek(0, io.SeekCurrent)
160+
if err != nil {
161+
return nil, err
162+
}
163+
if cur >= startPos + dataLen {
164+
break
165+
}
166+
}
167+
} else {
168+
if _, err := r.Seek(dataLen, io.SeekCurrent); err != nil {
169+
return nil, err
170+
}
171+
}
172+
173+
return &Atom {
174+
Name: name,
175+
DataStartPos: startPos,
176+
DataLen: dataLen,
177+
Children: catoms,
178+
}, nil
179+
}

0 commit comments

Comments
 (0)