new_video.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. package archive
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "time"
  7. "go-common/app/service/main/videoup/model/archive"
  8. "go-common/library/database/sql"
  9. "go-common/library/log"
  10. "go-common/library/xstr"
  11. farm "github.com/dgryski/go-farm"
  12. )
  13. const (
  14. _inVideoCidSQL = `INSERT IGNORE INTO video (id,filename,src_type,resolutions,playurl,status,xcode_state,duration,filesize,attribute,failcode,hash64)
  15. VALUES (?,?,?,?,?,?,?,?,?,?,?,?)`
  16. _inNewVideoSQL = `INSERT INTO video (filename,src_type,resolutions,playurl,status,xcode_state,duration,filesize,attribute,failcode,hash64)
  17. VALUES (?,?,?,?,?,?,?,?,?,?,?)`
  18. _inVideoRelationSQL = "INSERT IGNORE INTO archive_video_relation (id,aid,cid,title,description,index_order,ctime) VALUES (?,?,?,?,?,?,?)"
  19. _upVideoRelationSQL = "UPDATE archive_video_relation SET title=?,description=?,index_order=? ,state=? WHERE aid=? and cid=?"
  20. _upRelationStateSQL = "UPDATE archive_video_relation SET state=? WHERE aid=? AND cid=?"
  21. _upVideoStatusSQL = "UPDATE video SET status=? WHERE id=?"
  22. _upNewVideoSQL = "UPDATE video SET src_type=?,status=?,xcode_state=? WHERE id=?"
  23. _newVideoFnSQL = "SELECT id,filename,src_type,resolutions,playurl,status,xcode_state,duration,filesize,attribute,failcode,ctime,mtime,dimensions FROM video WHERE hash64=? AND filename=?"
  24. _newVideoByFnSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode,
  25. avr.index_order,v.attribute,v.xcode_state,avr.state,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id
  26. WHERE hash64=? AND filename=?`
  27. _newVideoDataCidsFnSQL = "SELECT id,filename FROM video WHERE hash64 in (%s) AND filename in (%s)"
  28. _newsimpleArcVideoSQL = `SELECT cid,title,index_order,state,mtime FROM archive_video_relation WHERE aid=?`
  29. _newVideosSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode,
  30. avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id
  31. WHERE aid=? ORDER BY index_order`
  32. _newvideoCidSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode,
  33. avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id
  34. WHERE cid=? ORDER BY id LIMIT 1`
  35. _newVideosCidSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode,
  36. avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id
  37. WHERE cid IN (%s)`
  38. _newVideosFnSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode,
  39. avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id
  40. WHERE hash64 in (%s) AND filename in (%s)`
  41. _newVidReasonSQL = `SELECT ava.vid,ava.reason FROM archive_video_audit ava LEFT JOIN archive_video_relation avr ON ava.vid=avr.id WHERE ava.aid=? AND avr.state!=-100`
  42. _newVideosTimeoutSQL = `SELECT id ,filename,ctime,mtime from video WHERE hash64 in (%s) AND filename in (%s)`
  43. )
  44. // TxAddVideoCid insert video to get cid.
  45. func (d *Dao) TxAddVideoCid(tx *sql.Tx, v *archive.Video) (cid int64, err error) {
  46. hash64 := int64(farm.Hash64([]byte(v.Filename)))
  47. res, err := tx.Exec(_inVideoCidSQL, v.Cid, v.Filename, v.SrcType, v.Resolutions, v.Playurl, v.Status, v.XcodeState, v.Duration, v.Filesize, v.Attribute, v.FailCode, hash64)
  48. if err != nil {
  49. log.Error("d.inVideoCid.Exec error(%v)", err)
  50. return
  51. }
  52. cid, err = res.LastInsertId()
  53. return
  54. }
  55. // AddNewVideo insert new video.
  56. func (d *Dao) AddNewVideo(c context.Context, v *archive.Video) (cid int64, err error) {
  57. hash64 := int64(farm.Hash64([]byte(v.Filename)))
  58. res, err := d.db.Exec(c, _inNewVideoSQL, v.Filename, v.SrcType, v.Resolutions, v.Playurl, v.Status, v.XcodeState, v.Duration, v.Filesize, v.Attribute, v.FailCode, hash64)
  59. if err != nil {
  60. log.Error("d.inNewVideo.Exec error(%v)", err)
  61. return
  62. }
  63. cid, err = res.LastInsertId()
  64. return
  65. }
  66. // TxAddNewVideo insert new video.
  67. func (d *Dao) TxAddNewVideo(tx *sql.Tx, v *archive.Video) (cid int64, err error) {
  68. hash64 := int64(farm.Hash64([]byte(v.Filename)))
  69. res, err := tx.Exec(_inNewVideoSQL, v.Filename, v.SrcType, v.Resolutions, v.Playurl, v.Status, v.XcodeState, v.Duration, v.Filesize, v.Attribute, v.FailCode, hash64)
  70. if err != nil {
  71. log.Error("tx.inNewVideo.Exec error(%v)", err)
  72. return
  73. }
  74. cid, err = res.LastInsertId()
  75. return
  76. }
  77. // TxAddVideoRelation insert archive_video_relation to get vid.
  78. func (d *Dao) TxAddVideoRelation(tx *sql.Tx, v *archive.Video) (vid int64, err error) {
  79. res, err := tx.Exec(_inVideoRelationSQL, v.ID, v.Aid, v.Cid, v.Title, v.Desc, v.Index, v.CTime)
  80. if err != nil {
  81. log.Error("d.inVideoRelation.Exec error(%v)", err)
  82. return
  83. }
  84. vid, err = res.LastInsertId()
  85. return
  86. }
  87. // TxUpVideoRelation update archive_video_relation info by aid and cid.
  88. func (d *Dao) TxUpVideoRelation(tx *sql.Tx, v *archive.Video) (rows int64, err error) {
  89. res, err := tx.Exec(_upVideoRelationSQL, v.Title, v.Desc, v.Index, archive.VideoStatusOpen, v.Aid, v.Cid)
  90. if err != nil {
  91. log.Error("d.upVideoRelation.Exec(%v) error(%v)", v, err)
  92. return
  93. }
  94. rows, err = res.RowsAffected()
  95. return
  96. }
  97. // TxUpRelationState update archive_video_relation state by aid and cid.
  98. func (d *Dao) TxUpRelationState(tx *sql.Tx, aid, cid int64, state int16) (rows int64, err error) {
  99. res, err := tx.Exec(_upRelationStateSQL, state, aid, cid)
  100. if err != nil {
  101. log.Error("d.upRelationState.Exec(%d,%d,%d) error(%v)", aid, cid, state, err)
  102. return
  103. }
  104. rows, err = res.RowsAffected()
  105. return
  106. }
  107. // TxUpVdoStatus update video state by cid.
  108. func (d *Dao) TxUpVdoStatus(tx *sql.Tx, cid int64, status int16) (rows int64, err error) {
  109. res, err := tx.Exec(_upVideoStatusSQL, status, cid)
  110. if err != nil {
  111. log.Error("d.upVideoStatus.Exec(%d,%d) error(%v)", cid, status, err)
  112. return
  113. }
  114. rows, err = res.RowsAffected()
  115. return
  116. }
  117. // TxUpNewVideo update video SrcType\Status\XcodeState by cid.
  118. func (d *Dao) TxUpNewVideo(tx *sql.Tx, v *archive.Video) (rows int64, err error) {
  119. res, err := tx.Exec(_upNewVideoSQL, v.SrcType, v.Status, v.XcodeState, v.Cid)
  120. if err != nil {
  121. log.Error("d.upSimNewVideo.Exec(%s,%d,%d,%d) error(%v)", v.SrcType, v.Status, v.XcodeState, v.Cid, err)
  122. return
  123. }
  124. rows, err = res.RowsAffected()
  125. return
  126. }
  127. // NewVideoFn get video by filename
  128. func (d *Dao) NewVideoFn(c context.Context, filename string) (v *archive.Video, err error) {
  129. hash64 := int64(farm.Hash64([]byte(filename)))
  130. row := d.rddb.QueryRow(c, _newVideoFnSQL, hash64, filename)
  131. v = &archive.Video{}
  132. var dimStr string
  133. if err = row.Scan(&v.Cid, &v.Filename, &v.SrcType, &v.Resolutions, &v.Playurl, &v.Status, &v.XcodeState, &v.Duration, &v.Filesize, &v.Attribute, &v.FailCode, &v.CTime, &v.MTime, &dimStr); err != nil {
  134. if err == sql.ErrNoRows {
  135. err = nil
  136. v = nil
  137. } else {
  138. log.Error("row.Scan error(%v)", err)
  139. }
  140. return
  141. }
  142. v.Dimension, _ = d.parseDimensions(dimStr)
  143. return
  144. }
  145. // NewVideoByFn get video by filename
  146. func (d *Dao) NewVideoByFn(c context.Context, filename string) (v *archive.Video, err error) {
  147. hash64 := int64(farm.Hash64([]byte(filename)))
  148. row := d.rddb.QueryRow(c, _newVideoByFnSQL, hash64, filename)
  149. v = &archive.Video{}
  150. var dimStr string
  151. if err = row.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
  152. &v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &v.Status, &v.CTime, &v.MTime, &dimStr); err != nil {
  153. if err == sql.ErrNoRows {
  154. v = nil
  155. err = nil
  156. } else {
  157. log.Error("row.Scan error(%v)", err)
  158. }
  159. return
  160. }
  161. v.Dimension, _ = d.parseDimensions(dimStr)
  162. return
  163. }
  164. // NewCidsByFns get cids map in batches by filenames and hash64s.
  165. func (d *Dao) NewCidsByFns(c context.Context, nvs []*archive.Video) (cids map[string]int64, err error) {
  166. var (
  167. buf bytes.Buffer
  168. hash64s []int64
  169. )
  170. for _, v := range nvs {
  171. buf.WriteByte('\'')
  172. buf.WriteString(v.Filename)
  173. buf.WriteString("',")
  174. hash64s = append(hash64s, int64(farm.Hash64([]byte(v.Filename))))
  175. }
  176. buf.Truncate(buf.Len() - 1)
  177. rows, err := d.rddb.Query(c, fmt.Sprintf(_newVideoDataCidsFnSQL, xstr.JoinInts(hash64s), buf.String()))
  178. if err != nil {
  179. log.Error("db.Query() error(%v)", err)
  180. return
  181. }
  182. defer rows.Close()
  183. cids = make(map[string]int64)
  184. for rows.Next() {
  185. var (
  186. cid int64
  187. filename string
  188. )
  189. if err = rows.Scan(&cid, &filename); err != nil {
  190. log.Error("rows.Scan error(%v)", err)
  191. return
  192. }
  193. cids[filename] = cid
  194. }
  195. return
  196. }
  197. // SimpleArcVideos get simple videos from avr
  198. func (d *Dao) SimpleArcVideos(c context.Context, aid int64) (vs []*archive.SimpleVideo, err error) {
  199. rows, err := d.rddb.Query(c, _newsimpleArcVideoSQL, aid)
  200. if err != nil {
  201. log.Error("d.videosStmt.Query(%d) error(%v)", aid, err)
  202. return
  203. }
  204. defer rows.Close()
  205. for rows.Next() {
  206. v := &archive.SimpleVideo{}
  207. if err = rows.Scan(&v.Cid, &v.Title, &v.Index, &v.Status, &v.MTime); err != nil {
  208. log.Error("rows.Scan error(%v)", err)
  209. return
  210. }
  211. vs = append(vs, v)
  212. }
  213. return
  214. }
  215. // NewVideos get videos info by aid.
  216. func (d *Dao) NewVideos(c context.Context, aid int64) (vs []*archive.Video, err error) {
  217. rows, err := d.rddb.Query(c, _newVideosSQL, aid)
  218. if err != nil {
  219. log.Error("d.videosStmt.Query(%d) error(%v)", aid, err)
  220. return
  221. }
  222. defer rows.Close()
  223. for rows.Next() {
  224. v := &archive.Video{}
  225. var (
  226. avrState, vState int16
  227. dimStr string
  228. )
  229. if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
  230. &v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil {
  231. log.Error("rows.Scan error(%v)", err)
  232. return
  233. }
  234. v.Dimension, _ = d.parseDimensions(dimStr)
  235. // 2 state map to 1
  236. if avrState == archive.VideoStatusDelete {
  237. v.Status = archive.VideoStatusDelete
  238. } else {
  239. v.Status = vState
  240. }
  241. vs = append(vs, v)
  242. }
  243. return
  244. }
  245. // NewVideoMap get video map info by aid.
  246. func (d *Dao) NewVideoMap(c context.Context, aid int64) (vm map[string]*archive.Video, cvm map[int64]*archive.Video, err error) {
  247. rows, err := d.rddb.Query(c, _newVideosSQL, aid)
  248. if err != nil {
  249. log.Error("d.videosStmt.Query(%d) error(%v)", aid, err)
  250. return
  251. }
  252. defer rows.Close()
  253. vm = make(map[string]*archive.Video)
  254. cvm = make(map[int64]*archive.Video)
  255. for rows.Next() {
  256. v := &archive.Video{}
  257. var (
  258. avrState, vState int16
  259. dimStr string
  260. )
  261. if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
  262. &v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil {
  263. log.Error("rows.Scan error(%v)", err)
  264. return
  265. }
  266. v.Dimension, _ = d.parseDimensions(dimStr)
  267. // 2 state map to 1
  268. if avrState == archive.VideoStatusDelete {
  269. v.Status = archive.VideoStatusDelete
  270. } else {
  271. v.Status = vState
  272. }
  273. cvm[v.Cid] = v
  274. vm[v.Filename] = v
  275. }
  276. return
  277. }
  278. // NewVideoByCID get video by cid.
  279. func (d *Dao) NewVideoByCID(c context.Context, cid int64) (v *archive.Video, err error) {
  280. row := d.rddb.QueryRow(c, _newvideoCidSQL, cid)
  281. v = &archive.Video{}
  282. var (
  283. avrState, vState int16
  284. dimStr string
  285. )
  286. if err = row.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
  287. &v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil {
  288. if err == sql.ErrNoRows {
  289. v = nil
  290. err = nil
  291. }
  292. log.Error("row.Scan error(%v)", err)
  293. return
  294. }
  295. v.Dimension, _ = d.parseDimensions(dimStr)
  296. // 2 state map to 1
  297. if avrState == archive.VideoStatusDelete {
  298. v.Status = archive.VideoStatusDelete
  299. } else {
  300. v.Status = vState
  301. }
  302. return
  303. }
  304. // NewVideosByCID multi get video by cids.
  305. func (d *Dao) NewVideosByCID(c context.Context, cids []int64) (vm map[int64]map[int64]*archive.Video, err error) {
  306. rows, err := d.rddb.Query(c, fmt.Sprintf(_newVideosCidSQL, xstr.JoinInts(cids)))
  307. if err != nil {
  308. log.Error("db.Query() error(%v)", err)
  309. return
  310. }
  311. defer rows.Close()
  312. vm = make(map[int64]map[int64]*archive.Video)
  313. for rows.Next() {
  314. var (
  315. avrState, vState int16
  316. dimStr string
  317. )
  318. v := &archive.Video{}
  319. if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
  320. &v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil {
  321. log.Error("rows.Scan error(%v)", err)
  322. return
  323. }
  324. v.Dimension, _ = d.parseDimensions(dimStr)
  325. // 2 state map to 1
  326. if avrState == archive.VideoStatusDelete {
  327. v.Status = archive.VideoStatusDelete
  328. } else {
  329. v.Status = vState
  330. }
  331. if vv, ok := vm[v.Aid]; !ok {
  332. vm[v.Aid] = map[int64]*archive.Video{
  333. v.Cid: v,
  334. }
  335. } else {
  336. vv[v.Cid] = v
  337. }
  338. }
  339. return
  340. }
  341. // NewVideosByFn multi get video by filenames.
  342. func (d *Dao) NewVideosByFn(c context.Context, fns []string) (vm map[int64]map[string]*archive.Video, err error) {
  343. var (
  344. buf bytes.Buffer
  345. hash64s []int64
  346. )
  347. for _, fn := range fns {
  348. buf.WriteByte('\'')
  349. buf.WriteString(fn)
  350. buf.WriteString("',")
  351. hash64s = append(hash64s, int64(farm.Hash64([]byte(fn))))
  352. }
  353. buf.Truncate(buf.Len() - 1)
  354. rows, err := d.rddb.Query(c, fmt.Sprintf(_newVideosFnSQL, xstr.JoinInts(hash64s), buf.String()))
  355. if err != nil {
  356. log.Error("db.Query() error(%v)", err)
  357. return
  358. }
  359. defer rows.Close()
  360. vm = make(map[int64]map[string]*archive.Video)
  361. for rows.Next() {
  362. var (
  363. avrState, vState int16
  364. dimStr string
  365. )
  366. v := &archive.Video{}
  367. if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
  368. &v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil {
  369. log.Error("rows.Scan error(%v)", err)
  370. return
  371. }
  372. v.Dimension, _ = d.parseDimensions(dimStr)
  373. // 2 state map to 1
  374. if avrState == archive.VideoStatusDelete {
  375. v.Status = archive.VideoStatusDelete
  376. } else {
  377. v.Status = vState
  378. }
  379. if vv, ok := vm[v.Aid]; !ok {
  380. vm[v.Aid] = map[string]*archive.Video{
  381. v.Filename: v,
  382. }
  383. } else {
  384. vv[v.Filename] = v
  385. }
  386. }
  387. return
  388. }
  389. // CheckNewVideosTimeout check 48 timeout by add filenames.
  390. func (d *Dao) CheckNewVideosTimeout(c context.Context, fns []string) (has bool, filename string, err error) {
  391. var (
  392. buf bytes.Buffer
  393. hash64s []int64
  394. )
  395. for _, fn := range fns {
  396. buf.WriteByte('\'')
  397. buf.WriteString(fn)
  398. buf.WriteString("',")
  399. hash64s = append(hash64s, int64(farm.Hash64([]byte(fn))))
  400. }
  401. buf.Truncate(buf.Len() - 1)
  402. rows, err := d.rddb.Query(c, fmt.Sprintf(_newVideosTimeoutSQL, xstr.JoinInts(hash64s), buf.String()))
  403. if err != nil {
  404. log.Error("db.Query() error(%v)", err)
  405. return
  406. }
  407. defer rows.Close()
  408. now := time.Now().Unix()
  409. for rows.Next() {
  410. v := &archive.VideoFn{}
  411. if err = rows.Scan(&v.Cid, &v.Filename, &v.CTime, &v.MTime); err != nil {
  412. log.Error("rows.Scan error(%v)", err)
  413. return
  414. }
  415. if now-v.CTime.Time().Unix() > archive.VideoFilenameTimeout {
  416. log.Error("this video filename(%v) timeout (%+v)", v.Filename, v)
  417. has = true
  418. filename = v.Filename
  419. err = nil
  420. return
  421. }
  422. }
  423. return
  424. }
  425. // NewVideosReason get videos audit reason.
  426. func (d *Dao) NewVideosReason(c context.Context, aid int64) (res map[int64]string, err error) {
  427. rows, err := d.rddb.Query(c, _newVidReasonSQL, aid)
  428. if err != nil {
  429. log.Error("d.vdoRsnStmt.Query(%d)|error(%v)", aid, err)
  430. return
  431. }
  432. defer rows.Close()
  433. res = make(map[int64]string)
  434. for rows.Next() {
  435. var (
  436. vid int64
  437. reason string
  438. )
  439. if err = rows.Scan(&vid, &reason); err != nil {
  440. log.Error("rows.Scan error(%v)", err)
  441. return
  442. }
  443. res[vid] = reason
  444. }
  445. return
  446. }
  447. // parseDimensions 解析分辨率
  448. func (d *Dao) parseDimensions(dim string) (dimensions *archive.Dimension, err error) {
  449. dimensions = &archive.Dimension{}
  450. if dim == "" || dim == "0,0,0" {
  451. return
  452. }
  453. dims, err := xstr.SplitInts(dim)
  454. if err != nil {
  455. log.Error("d.parseDimensions() xstr.SplitInts(%s) error(%v)", dim, err)
  456. return
  457. }
  458. if len(dims) != 3 {
  459. return
  460. }
  461. dimensions = &archive.Dimension{
  462. Width: dims[0],
  463. Height: dims[1],
  464. Rotate: dims[2],
  465. }
  466. return
  467. }