@@ -52,10 +52,21 @@ def metadata_pages(self, pages: Optional[List[UsmPage]]):
5252 def channel_number (self ) -> int :
5353 return self ._channel_number
5454
55+ @channel_number .setter
56+ def channel_number (self , new_channel_number : int ):
57+ if new_channel_number < 0 :
58+ raise ValueError (f"Given negative channel number: { new_channel_number } " )
59+
60+ self ._channel_number = new_channel_number
61+
5562 @property
5663 def header_page (self ) -> UsmPage :
5764 return self ._header_page
5865
66+ @header_page .setter
67+ def header_page (self , new_header_page : UsmPage ):
68+ self ._header_page = new_header_page
69+
5970 @property
6071 def filename (self ) -> str :
6172 """A slugified filename, which is stored inside the crid_page.
@@ -68,6 +79,12 @@ def filename(self) -> str:
6879 result : str = filename .val .split ("/" )[- 1 ]
6980 return slugify (result , allow_unicode = True )
7081
82+ @filename .setter
83+ def filename (self , new_filename : str ):
84+ new_filename = slugify (new_filename , allow_unicode = True )
85+ self .crid_page ["filename" ].type = ElementType .STRING
86+ self .crid_page ["filename" ].val = new_filename
87+
7188 def __len__ (self ) -> int :
7289 """The number of packets a Usm videos or audios has."""
7390 return self ._length
@@ -89,6 +106,7 @@ class UsmVideo(UsmMedia, Protocol):
89106 # Classes that explicitly inherit UsmVideo should have this attribute
90107 # to use the default stream and chunks methods.
91108 _stream : Generator [Tuple [bytes , bool ], None , None ]
109+ is_alpha : bool
92110
93111 def stream (
94112 self , mode : OpMode = OpMode .NONE , key : Optional [bytes ] = None
@@ -317,246 +335,3 @@ def chunks(
317335 channel_number = self .channel_number ,
318336 ),
319337 ]
320-
321-
322- # TODO: Delete the comments when done rewriting
323-
324- # class VP9:
325- # def __init__(self, filepath: str):
326- # self.filename = os.path.basename(filepath)
327- # self.filesize = os.path.getsize(filepath)
328- # self.info = ffmpeg.probe(filepath, show_entries="packet=dts,pts_time,pos,flags")
329-
330- # if len(self.info.get("streams")) == 0:
331- # raise Exception("No streams found")
332- # elif len(self.info.get("streams")) > 1:
333- # raise NotImplementedError("Can only accept one stream")
334- # elif self.info.get("format").get("format_name") != "ivf":
335- # raise Exception("Not an ivf file")
336- # elif self.info.get("streams")[0].get("codec_name") != "vp9":
337- # raise Exception("Not a VP9 videos")
338-
339- # video_stream = self.info.get("streams")[0]
340- # self.bitrate = int(self.info.get("format").get("bit_rate"))
341- # self.width = int(video_stream.get("width"))
342- # self.height = int(video_stream.get("height"))
343- # self.framerate_n = int(video_stream.get("r_frame_rate").split("/")[0])
344- # self.framerate_d = int(video_stream.get("r_frame_rate").split("/")[1])
345-
346- # self.frames = self.info.get("packets")
347- # self.keyframes = [frame for frame in self.frames if frame.get("flags") == "K_"]
348- # self.total_frames = len(self.frames)
349- # self.file = open(filepath, "rb")
350-
351- # def export(
352- # self, encrypt: bool, key: Optional[int] = None, encoding: str = "UTF-8"
353- # ) -> bytes:
354- # if encrypt:
355- # video_key1, video_key2, _ = generate_keys(key)
356-
357- # debug = open("FRAME_TIME_DEBUG", "w+")
358- # stream_chunks = bytearray()
359- # keyframe_usm_offsets = []
360- # max_frame_size = 0
361- # max_packed_frame_size = 0
362- # max_keyframe_to_keyframe_size = 0
363- # current_keyframe_to_keyframe_size = 0
364- # self.file.seek(0, 0)
365- # for i, frame in enumerate(self.frames):
366- # # frame_time formula is based on existing usm files.
367- # # TODO: Does this hold up for videos that's not 30fps?
368- # debug.write("Frame {}: time = {}".format(i, frame.get("pts_time")))
369- # # frame_time = int(99.86891 * i)
370- # frame_time = int(i * 99.9)
371- # if frame in self.keyframes:
372- # keyframe_usm_offsets.append(len(stream_chunks))
373-
374- # if i == len(self.frames) - 1:
375- # # Last frame
376- # frame_size = self.filesize - int(frame.get("pos"))
377- # else:
378- # frame_size = int(self.frames[i + 1].get("pos")) - int(frame.get("pos"))
379-
380- # if i == 0:
381- # # Include 32 byte header for first frame
382- # max_frame_size = frame_size + 32
383- # packet = self.file.read(frame_size + 32)
384- # else:
385- # if frame_size > max_frame_size:
386- # max_frame_size = frame_size
387-
388- # packet = self.file.read(frame_size)
389-
390- # if frame.get("flags") != "K_":
391- # current_keyframe_to_keyframe_size += frame_size
392- # elif current_keyframe_to_keyframe_size > max_keyframe_to_keyframe_size:
393- # max_keyframe_to_keyframe_size = current_keyframe_to_keyframe_size
394- # current_keyframe_to_keyframe_size = frame_size
395-
396- # if encrypt:
397- # packet = encrypt_video_packet(packet, video_key1, video_key2)
398-
399- # padding_size = 0x20 - (len(packet) % 0x20) if len(packet) % 0x20 != 0 else 0
400- # packed_frame_chunk = generate_packed_chunk(
401- # "@SFV",
402- # 0,
403- # int(100 * self.framerate_n / self.framerate_d),
404- # frame_time,
405- # packet,
406- # padding_size,
407- # )
408- # if len(packed_frame_chunk) > max_packed_frame_size:
409- # max_packed_frame_size = len(packed_frame_chunk)
410-
411- # stream_chunks += packed_frame_chunk
412-
413- # stream_chunks += generate_packed_chunk(
414- # "@SFV",
415- # 2,
416- # int(self.framerate_n / self.framerate_d),
417- # 0,
418- # bytes("#CONTENTS END ===============", "UTF-8") + bytes(1),
419- # 0,
420- # )
421-
422- # seek_chunks = bytearray()
423- # keyframe_pages = []
424- # video_header_end_offset = get_video_header_end_offset(len(self.keyframes))
425- # # Offset of videos header end offset plus length of videos header end
426- # stream_offset = video_header_end_offset + 0x40
427- # for i, keyframe in enumerate(self.keyframes):
428- # keyframe_usm_offset = keyframe_usm_offsets[i]
429- # keyframe_offset = stream_offset + keyframe_usm_offset
430- # keyframe_page = UsmPage("VIDEO_SEEKINFO", i)
431- # keyframe_page.add("ofs_byte", ElementType.clonglong, keyframe_offset)
432- # keyframe_page.add("ofs_frmid", ElementType.cuint, keyframe.get("dts"))
433- # keyframe_page.add("num_skip", ElementType.cushort, 0)
434- # keyframe_page.add("resv", ElementType.cushort, 0)
435- # keyframe_pages.append(keyframe_page)
436-
437- # seek_chunks_payload = pack_pages(keyframe_pages, string_padding=1)
438- # # 0x20 bytes for chunk header.
439- # seek_chunks_padding = (
440- # video_header_end_offset - 0xA40 - 0x20 - len(seek_chunks_payload)
441- # )
442- # seek_chunks += generate_packed_chunk(
443- # "@SFV",
444- # 3,
445- # int(self.framerate_n / self.framerate_d),
446- # 0,
447- # seek_chunks_payload,
448- # seek_chunks_padding,
449- # )
450- # metadata_size = len(seek_chunks)
451- # seek_chunks += generate_packed_chunk(
452- # "@SFV",
453- # 2,
454- # int(self.framerate_n / self.framerate_d),
455- # 0,
456- # bytes("#METADATA END ===============", "UTF-8") + bytes(1),
457- # 0,
458- # )
459-
460- # header_page = UsmPage("VIDEO_HDRINFO", 0)
461- # header_page.add("width", ElementType.cint, self.width)
462- # header_page.add("height", ElementType.cint, self.height)
463- # header_page.add("mat_width", ElementType.cint, self.width)
464- # header_page.add("mat_height", ElementType.cint, self.height)
465- # header_page.add("disp_width", ElementType.cint, self.width)
466- # header_page.add("disp_height", ElementType.cint, self.height)
467- # header_page.add("scrn_width", ElementType.cint, 0)
468- # header_page.add("mpeg_dcprec", ElementType.cchar, 0)
469- # header_page.add("mpeg_codec", ElementType.cchar, 9)
470- # # TODO: Check if videos has transparency
471- # header_page.add("alpha_type", ElementType.cint, 0)
472- # header_page.add("total_frames", ElementType.cint, self.total_frames)
473-
474- # framerate_n = self.framerate_n
475- # framerate_d = self.framerate_d
476-
477- # if framerate_d < 1000 and framerate_d != 1000:
478- # framerate_d *= 1000
479- # framerate_n *= 1000
480-
481- # header_page.add("framerate_n", ElementType.cint, framerate_n)
482- # header_page.add("framerate_d", ElementType.cint, framerate_d)
483- # header_page.add("metadata_count", ElementType.cint, 1)
484- # header_page.add("metadata_size", ElementType.cint, metadata_size)
485- # header_page.add("ixsize", ElementType.cint, max_packed_frame_size)
486- # header_page.add("pre_padding", ElementType.cint, 0)
487- # header_page.add("max_picture_size", ElementType.cint, 0)
488- # header_page.add("color_space", ElementType.cint, 0)
489- # header_page.add("picture_type", ElementType.cint, 0)
490-
491- # header_chunk_payload = pack_pages([header_page])
492- # header_chunk_padding = 0xA00 - 0x800 - 0x20 - len(header_chunk_payload)
493- # header_chunk = bytearray()
494- # header_chunk += generate_packed_chunk(
495- # "@SFV",
496- # 1,
497- # int(self.framerate_n / self.framerate_d),
498- # 0,
499- # header_chunk_payload,
500- # header_chunk_padding,
501- # )
502- # header_chunk += generate_packed_chunk(
503- # "@SFV",
504- # 2,
505- # int(self.framerate_n / self.framerate_d),
506- # 0,
507- # bytes("#HEADER END ===============", "UTF-8") + bytes(1),
508- # 0,
509- # )
510-
511- # directory_pages = []
512- # for i in range(0, 2):
513- # if i == 0:
514- # filename = os.path.splitext(self.filename)[0] + ".usm"
515- # # filename = r"I:\000125 千本桜\000125.usm"
516- # filesize = (
517- # 0x800 + len(header_chunk) + len(seek_chunks) + len(stream_chunks)
518- # )
519- # stmid = 0
520- # chno = -1
521- # minchk = 1
522- # # TODO: Find formula for minbuf for usm
523- # minbuf = round(1.98746 * max_frame_size)
524- # minbuf += 0x10 - (minbuf % 0x10) if minbuf % 0x10 != 0 else 0
525- # else:
526- # filename = self.filename
527- # # filename = r"I:\000125 千本桜\000125.ivf"
528-
529- # filesize = self.filesize
530- # stmid = 1079199318 # @SFV
531- # chno = 0
532- # minchk = 3
533- # minbuf = max_frame_size
534-
535- # directory_part = UsmPage("CRIUSF_DIR_STREAM", 0)
536- # directory_part.add("fmtver", ElementType.cint, 16777984)
537- # directory_part.add("filename", ElementType.cstring, filename)
538- # directory_part.add("filesize", ElementType.cint, filesize)
539- # directory_part.add("datasize", ElementType.cint, 0)
540- # directory_part.add("stmid", ElementType.cint, stmid)
541- # directory_part.add("chno", ElementType.cshort, chno)
542- # directory_part.add("minchk", ElementType.cshort, minchk)
543- # directory_part.add("minbuf", ElementType.cint, minbuf)
544- # directory_part.add("avbps", ElementType.cint, self.bitrate)
545- # directory_pages.append(directory_part)
546-
547- # directory_chunk_payload = pack_pages(directory_pages, encoding, 5)
548- # directory_chunk_padding = 0x800 - 0x20 - len(directory_chunk_payload)
549- # directory_chunk = bytearray()
550- # directory_chunk += generate_packed_chunk(
551- # "CRID",
552- # 1,
553- # int(self.framerate_n / self.framerate_d),
554- # 0,
555- # directory_chunk_payload,
556- # directory_chunk_padding,
557- # )
558- # result = directory_chunk + header_chunk + seek_chunks + stream_chunks
559- # return bytes(result)
560-
561- # def close(self):
562- # self.file.close()
0 commit comments