github.com/0chain/gosdk@v1.17.11/wasmsdk/player_file.go (about) 1 //go:build js && wasm 2 // +build js,wasm 3 4 package main 5 6 import ( 7 "context" 8 "fmt" 9 10 "github.com/0chain/gosdk/zboxcore/marker" 11 "github.com/0chain/gosdk/zboxcore/sdk" 12 ) 13 14 type FilePlayer struct { 15 allocationID string 16 remotePath string 17 authTicket string 18 lookupHash string 19 numBlocks int 20 21 isViewer bool 22 allocationObj *sdk.Allocation 23 authTicketObj *marker.AuthTicket 24 playlistFile *sdk.PlaylistFile 25 26 downloadedChunks chan []byte 27 downloadedLen int 28 ctx context.Context 29 cancel context.CancelFunc 30 prefetchQty int 31 } 32 33 func (p *FilePlayer) Start() error { 34 if p.cancel != nil { 35 p.cancel() 36 } 37 38 p.ctx, p.cancel = context.WithCancel(context.TODO()) 39 40 file, err := p.loadPlaylistFile() 41 if err != nil { 42 return err 43 } 44 45 p.playlistFile = file 46 47 p.downloadedChunks = make(chan []byte, p.prefetchQty) 48 49 go p.startDownload() 50 51 return nil 52 } 53 54 func (p *FilePlayer) Stop() { 55 if p.cancel != nil { 56 p.cancel() 57 p.cancel = nil 58 } 59 } 60 61 func (p *FilePlayer) download(startBlock int64) { 62 endBlock := startBlock + int64(p.numBlocks) - 1 63 64 if endBlock > p.playlistFile.NumBlocks { 65 endBlock = p.playlistFile.NumBlocks 66 } 67 fmt.Println("start:", startBlock, "end:", endBlock, "numBlocks:", p.numBlocks, "total:", p.playlistFile.NumBlocks) 68 69 data, err := downloadBlocks(p.allocationObj.ID, p.remotePath, p.authTicket, p.lookupHash, startBlock, endBlock) 70 // data, err := downloadBlocks2(int(startBlock), int(endBlock), p.allocationObj, p.remotePath) 71 if err != nil { 72 PrintError(err.Error()) 73 return 74 } 75 withRecover(func() { 76 if p.downloadedChunks != nil { 77 p.downloadedChunks <- data 78 } 79 }) 80 } 81 82 func (p *FilePlayer) startDownload() { 83 fmt.Println("start download") 84 if p.playlistFile.NumBlocks < 1 { 85 PrintError("playlist: numBlocks is invalid") 86 return 87 } 88 var startBlock int64 = 1 89 for { 90 select { 91 case <-p.ctx.Done(): 92 PrintInfo("playlist: download is cancelled") 93 return 94 default: 95 fmt.Println("download start:", startBlock) 96 p.download(startBlock) 97 98 startBlock += int64(p.numBlocks) 99 fmt.Println("download end, new start:", startBlock) 100 101 if startBlock > p.playlistFile.NumBlocks { 102 103 go func() { 104 // trigger js to close stream 105 p.downloadedChunks <- nil 106 }() 107 return 108 } 109 110 } 111 } 112 113 } 114 115 func (p *FilePlayer) loadPlaylistFile() (*sdk.PlaylistFile, error) { 116 if p.isViewer { 117 //get playlist file from auth ticket 118 return sdk.GetPlaylistFileByAuthTicket(p.ctx, p.allocationObj, p.authTicket, p.lookupHash) 119 } 120 121 d, err := p.allocationObj.ListDir(p.remotePath) 122 if err != nil { 123 fmt.Println("could not list dir:", p.remotePath) 124 return nil, err 125 } 126 f := d.Children[0] 127 var ( 128 dataShards = p.allocationObj.DataShards 129 effectivePerShardSize = (int(f.ActualSize) + dataShards - 1) / dataShards 130 totalBlocks = (effectivePerShardSize + sdk.DefaultChunkSize - 1) / sdk.DefaultChunkSize 131 ) 132 133 fmt.Println("totalBlocks:", totalBlocks) 134 fmt.Println("file size:", f.Size) 135 136 return &sdk.PlaylistFile{ 137 Name: f.Name, 138 Path: f.Path, 139 LookupHash: f.LookupHash, 140 NumBlocks: int64(totalBlocks), 141 Size: f.Size, 142 ActualFileSize: f.ActualSize, 143 MimeType: f.MimeType, 144 Type: f.Type, 145 }, nil 146 } 147 148 func (p *FilePlayer) GetNext() []byte { 149 b, ok := <-p.downloadedChunks 150 if ok { 151 if p.downloadedLen+len(b) > int(p.playlistFile.ActualFileSize) { 152 b = b[:int(p.playlistFile.ActualFileSize)-p.downloadedLen] 153 } 154 p.downloadedLen += len(b) 155 return b 156 } 157 158 return nil 159 } 160 161 // createFilePalyer create player for remotePath 162 func createFilePalyer(allocationID, remotePath, authTicket, lookupHash string) (*FilePlayer, error) { 163 player := &FilePlayer{} 164 player.prefetchQty = 3 165 player.remotePath = remotePath 166 player.authTicket = authTicket 167 player.lookupHash = lookupHash 168 player.numBlocks = 10 169 player.allocationID = allocationID 170 171 //player is viewer 172 if len(authTicket) > 0 { 173 //player is viewer via shared authticket 174 at, err := sdk.InitAuthTicket(authTicket).Unmarshall() 175 176 if err != nil { 177 PrintError(err) 178 return nil, err 179 } 180 181 allocationObj, err := sdk.GetAllocationFromAuthTicket(authTicket) 182 if err != nil { 183 PrintError("Error fetching the allocation", err) 184 return nil, err 185 } 186 187 player.isViewer = true 188 player.allocationObj = allocationObj 189 player.authTicketObj = at 190 player.lookupHash = at.FilePathHash 191 192 return player, nil 193 194 } 195 196 if len(allocationID) == 0 { 197 return nil, RequiredArg("allocationID") 198 } 199 200 allocationObj, err := sdk.GetAllocation(allocationID) 201 if err != nil { 202 PrintError("Error fetching the allocation", err) 203 return nil, err 204 } 205 206 player.isViewer = false 207 player.allocationObj = allocationObj 208 209 return player, nil 210 }