deffcode 0.2.5__py3-none-any.whl → 0.2.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- deffcode/ffdecoder.py +64 -28
- deffcode/ffhelper.py +20 -14
- deffcode/sourcer.py +84 -29
- deffcode/version.py +1 -1
- {deffcode-0.2.5.dist-info → deffcode-0.2.6.dist-info}/METADATA +12 -12
- deffcode-0.2.6.dist-info/RECORD +11 -0
- {deffcode-0.2.5.dist-info → deffcode-0.2.6.dist-info}/WHEEL +1 -1
- deffcode-0.2.5.dist-info/RECORD +0 -11
- {deffcode-0.2.5.dist-info → deffcode-0.2.6.dist-info}/LICENSE +0 -0
- {deffcode-0.2.5.dist-info → deffcode-0.2.6.dist-info}/top_level.txt +0 -0
deffcode/ffdecoder.py
CHANGED
|
@@ -19,6 +19,7 @@ limitations under the License.
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
# import the necessary packages
|
|
22
|
+
import platform
|
|
22
23
|
import logging
|
|
23
24
|
import numpy as np
|
|
24
25
|
import subprocess as sp
|
|
@@ -106,10 +107,16 @@ class FFdecoder:
|
|
|
106
107
|
# handles user-defined parameters
|
|
107
108
|
self.__extra_params = {}
|
|
108
109
|
|
|
109
|
-
#
|
|
110
|
+
# handles process to be frames written
|
|
110
111
|
self.__process = None
|
|
111
112
|
|
|
112
|
-
#
|
|
113
|
+
# handles disabling window for ffmpeg subprocess on Windows
|
|
114
|
+
self.__ffmpeg_window_disabler_patch = False
|
|
115
|
+
|
|
116
|
+
# checks machine OS
|
|
117
|
+
self.__machine_OS = platform.system()
|
|
118
|
+
|
|
119
|
+
# handles exclusive metadata
|
|
113
120
|
self.__ff_pixfmt_metadata = None # metadata
|
|
114
121
|
self.__raw_frame_num = None # raw-frame number
|
|
115
122
|
self.__raw_frame_pixfmt = None # raw-frame pixformat
|
|
@@ -127,23 +134,26 @@ class FFdecoder:
|
|
|
127
134
|
# operation mode variable
|
|
128
135
|
self.__opmode = None
|
|
129
136
|
|
|
130
|
-
#
|
|
137
|
+
# handles termination
|
|
131
138
|
self.__terminate_stream = False
|
|
132
139
|
|
|
133
140
|
# cleans and reformat user-defined parameters
|
|
134
141
|
self.__extra_params = {
|
|
135
|
-
str(k).strip():
|
|
136
|
-
|
|
137
|
-
|
|
142
|
+
str(k).strip(): (
|
|
143
|
+
str(v).strip()
|
|
144
|
+
if not (v is None)
|
|
145
|
+
and not isinstance(v, (dict, list, int, float, tuple))
|
|
146
|
+
else v
|
|
147
|
+
)
|
|
138
148
|
for k, v in ffparams.items()
|
|
139
149
|
}
|
|
140
150
|
|
|
141
|
-
#
|
|
151
|
+
# handles custom Sourcer API params
|
|
142
152
|
sourcer_params = self.__extra_params.pop("-custom_sourcer_params", {})
|
|
143
153
|
# reset improper values
|
|
144
154
|
sourcer_params = {} if not isinstance(sourcer_params, dict) else sourcer_params
|
|
145
155
|
|
|
146
|
-
#
|
|
156
|
+
# handles user ffmpeg pre-headers(parameters such as `-re`) parameters (must be a list)
|
|
147
157
|
self.__ffmpeg_prefixes = self.__extra_params.pop("-ffprefixes", [])
|
|
148
158
|
# check if not valid type
|
|
149
159
|
if not isinstance(self.__ffmpeg_prefixes, list):
|
|
@@ -205,9 +215,29 @@ class FFdecoder:
|
|
|
205
215
|
if not (isinstance(self.__cv_patch, bool)):
|
|
206
216
|
self.__cv_patch = False
|
|
207
217
|
self.__verbose_logs and logger.critical(
|
|
208
|
-
"Enforcing OpenCV compatibility patch for YUV/NV frames."
|
|
218
|
+
"Enforcing OpenCV compatibility patch for YUV/NV video frames."
|
|
209
219
|
)
|
|
210
220
|
|
|
221
|
+
# handle disabling window for ffmpeg subprocess on Windows OS
|
|
222
|
+
# this patch prevents ffmpeg creation window from opening when
|
|
223
|
+
# building exe files
|
|
224
|
+
ffmpeg_window_disabler_patch = self.__extra_params.pop(
|
|
225
|
+
"-disable_ffmpeg_window", False
|
|
226
|
+
)
|
|
227
|
+
if ffmpeg_window_disabler_patch and isinstance(
|
|
228
|
+
ffmpeg_window_disabler_patch, bool
|
|
229
|
+
):
|
|
230
|
+
# check if value is valid
|
|
231
|
+
if self.__machine_OS != "Windows" or self.__verbose_logs:
|
|
232
|
+
logger.warning(
|
|
233
|
+
"Optional `-disable_ffmpeg_window` flag is only available on Windows OS with `verbose=False`. Discarding!"
|
|
234
|
+
)
|
|
235
|
+
else:
|
|
236
|
+
self.__ffmpeg_window_disabler_patch = ffmpeg_window_disabler_patch
|
|
237
|
+
else:
|
|
238
|
+
# handle improper values
|
|
239
|
+
self.__ffmpeg_window_disabler_patch = False
|
|
240
|
+
|
|
211
241
|
# handle pass-through audio mode works in conjunction with WriteGear [TODO]
|
|
212
242
|
self.__passthrough_mode = self.__extra_params.pop("-passthrough_audio", False)
|
|
213
243
|
if not (isinstance(self.__passthrough_mode, bool)):
|
|
@@ -288,7 +318,6 @@ class FFdecoder:
|
|
|
288
318
|
self.__custom_resolution = None
|
|
289
319
|
|
|
290
320
|
def formulate(self):
|
|
291
|
-
|
|
292
321
|
"""
|
|
293
322
|
This method formulates all necessary FFmpeg pipeline arguments and executes it inside the FFmpeg `subprocess` pipe.
|
|
294
323
|
|
|
@@ -420,13 +449,15 @@ class FFdecoder:
|
|
|
420
449
|
else:
|
|
421
450
|
logger.warning(
|
|
422
451
|
"{} Switching to default `{}` pixel-format!".format(
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
452
|
+
(
|
|
453
|
+
"Provided FFmpeg does not supports `{}` pixel-format.".format(
|
|
454
|
+
self.__sourcer_metadata["output_frames_pixfmt"]
|
|
455
|
+
if "output_frames_pixfmt" in self.__sourcer_metadata
|
|
456
|
+
else self.__frame_format
|
|
457
|
+
)
|
|
458
|
+
if self.__frame_format != "null"
|
|
459
|
+
else "No usable pixel-format defined."
|
|
460
|
+
),
|
|
430
461
|
default_pixfmt,
|
|
431
462
|
)
|
|
432
463
|
)
|
|
@@ -467,9 +498,9 @@ class FFdecoder:
|
|
|
467
498
|
self.__raw_frame_pixfmt = rawframe_pixfmt
|
|
468
499
|
# also override as metadata(if available)
|
|
469
500
|
if "output_frames_pixfmt" in self.__sourcer_metadata:
|
|
470
|
-
self.__sourcer_metadata[
|
|
471
|
-
|
|
472
|
-
|
|
501
|
+
self.__sourcer_metadata["output_frames_pixfmt"] = (
|
|
502
|
+
self.__raw_frame_pixfmt
|
|
503
|
+
)
|
|
473
504
|
|
|
474
505
|
# handle raw-frame resolution
|
|
475
506
|
# notify FFmpeg `-s` parameter cannot be assigned directly
|
|
@@ -804,9 +835,11 @@ class FFdecoder:
|
|
|
804
835
|
self.__verbose_logs and logger.info(
|
|
805
836
|
"Updating `{}`{} metadata property to `{}`.".format(
|
|
806
837
|
key,
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
838
|
+
(
|
|
839
|
+
" and its counterpart"
|
|
840
|
+
if key in counterpart_prop.values()
|
|
841
|
+
else ""
|
|
842
|
+
),
|
|
810
843
|
value[key],
|
|
811
844
|
)
|
|
812
845
|
)
|
|
@@ -838,7 +871,6 @@ class FFdecoder:
|
|
|
838
871
|
raise ValueError("Invalid datatype metadata assigned. Aborting!")
|
|
839
872
|
|
|
840
873
|
def __launch_FFdecoderline(self, input_params, output_params):
|
|
841
|
-
|
|
842
874
|
"""
|
|
843
875
|
This Internal method executes FFmpeg pipeline arguments inside a `subprocess` pipe in a new process.
|
|
844
876
|
|
|
@@ -877,7 +909,13 @@ class FFdecoder:
|
|
|
877
909
|
else:
|
|
878
910
|
# In silent mode
|
|
879
911
|
self.__process = sp.Popen(
|
|
880
|
-
cmd,
|
|
912
|
+
cmd,
|
|
913
|
+
stdin=sp.DEVNULL,
|
|
914
|
+
stdout=sp.PIPE,
|
|
915
|
+
stderr=sp.DEVNULL,
|
|
916
|
+
creationflags=( # this prevents ffmpeg creation window from opening when building exe files on Windows
|
|
917
|
+
sp.DETACHED_PROCESS if self.__ffmpeg_window_disabler_patch else 0
|
|
918
|
+
),
|
|
881
919
|
)
|
|
882
920
|
|
|
883
921
|
def terminate(self):
|
|
@@ -898,9 +936,7 @@ class FFdecoder:
|
|
|
898
936
|
# close `stdout` output
|
|
899
937
|
self.__process.stdout and self.__process.stdout.close()
|
|
900
938
|
# terminate/kill process if still processing
|
|
901
|
-
|
|
902
|
-
# demuxers prefer kill
|
|
903
|
-
self.__process.kill()
|
|
939
|
+
self.__process.poll() is None and self.__process.terminate()
|
|
904
940
|
# wait if not exiting
|
|
905
941
|
self.__process.wait()
|
|
906
942
|
self.__process = None
|
deffcode/ffhelper.py
CHANGED
|
@@ -342,14 +342,15 @@ def get_supported_demuxers(path):
|
|
|
342
342
|
|
|
343
343
|
**Returns:** List of supported demuxers.
|
|
344
344
|
"""
|
|
345
|
+
# extract and clean FFmpeg output
|
|
345
346
|
demuxers = check_sp_output([path, "-hide_banner", "-demuxers"])
|
|
346
347
|
splitted = [x.decode("utf-8").strip() for x in demuxers.split(b"\n")]
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
outputs =
|
|
352
|
-
# return output
|
|
348
|
+
split_index = [idx for idx, s in enumerate(splitted) if "--" in s][0]
|
|
349
|
+
supported_demuxers = splitted[split_index + 1 : len(splitted) - 1]
|
|
350
|
+
# search all demuxers
|
|
351
|
+
outputs = [re.search(r"\s[a-z0-9_,-]{2,}\s", d) for d in supported_demuxers]
|
|
352
|
+
outputs = [o.group(0) for o in outputs if o]
|
|
353
|
+
# return demuxers output
|
|
353
354
|
return [o.strip() if not ("," in o) else o.split(",")[-1].strip() for o in outputs]
|
|
354
355
|
|
|
355
356
|
|
|
@@ -518,10 +519,12 @@ def extract_device_n_demuxer(path, machine_OS=None, verbose=False):
|
|
|
518
519
|
logger.info(
|
|
519
520
|
"[{}]: {}".format(
|
|
520
521
|
idx,
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
522
|
+
(
|
|
523
|
+
dev
|
|
524
|
+
if machine_OS != "Linux"
|
|
525
|
+
else "{} at path `{}`".format(
|
|
526
|
+
next(iter(dev.values()))[0], next(iter(dev.keys()))
|
|
527
|
+
)
|
|
525
528
|
),
|
|
526
529
|
)
|
|
527
530
|
)
|
|
@@ -632,8 +635,11 @@ def is_valid_url(path, url=None, verbose=False):
|
|
|
632
635
|
protocols = check_sp_output([path, "-hide_banner", "-protocols"])
|
|
633
636
|
splitted = [x.decode("utf-8").strip() for x in protocols.split(b"\n")]
|
|
634
637
|
supported_protocols = splitted[splitted.index("Output:") + 1 : len(splitted) - 1]
|
|
635
|
-
#
|
|
636
|
-
|
|
638
|
+
# RTSP is a demuxer somehow
|
|
639
|
+
# support both RTSP and RTSPS(over SSL)
|
|
640
|
+
supported_protocols += (
|
|
641
|
+
["rtsp", "rtsps"] if "rtsp" in get_supported_demuxers(path) else []
|
|
642
|
+
)
|
|
637
643
|
# Test and return result whether scheme is supported
|
|
638
644
|
if extracted_scheme_url and extracted_scheme_url in supported_protocols:
|
|
639
645
|
verbose and logger.debug(
|
|
@@ -677,7 +683,7 @@ def check_sp_output(*args, **kwargs):
|
|
|
677
683
|
retcode = process.poll()
|
|
678
684
|
# handle return code
|
|
679
685
|
if retcode and not (retrieve_stderr):
|
|
680
|
-
logger.error("[
|
|
686
|
+
logger.error("[Pipeline-Error] :: {}".format(output.decode("utf-8")))
|
|
681
687
|
cmd = kwargs.get("args")
|
|
682
688
|
if cmd is None:
|
|
683
689
|
cmd = args[0]
|
|
@@ -686,7 +692,7 @@ def check_sp_output(*args, **kwargs):
|
|
|
686
692
|
raise error
|
|
687
693
|
# raise error if no output
|
|
688
694
|
bool(output) or bool(stderr) or logger.error(
|
|
689
|
-
"[
|
|
695
|
+
"[Pipeline-Error] :: Pipeline failed to exact any data from command: {}!".format(
|
|
690
696
|
args[0] if args else []
|
|
691
697
|
)
|
|
692
698
|
)
|
deffcode/sourcer.py
CHANGED
|
@@ -87,7 +87,7 @@ class Sourcer:
|
|
|
87
87
|
verbose (bool): enables/disables verbose.
|
|
88
88
|
sourcer_params (dict): provides the flexibility to control supported internal and FFmpeg parameters.
|
|
89
89
|
"""
|
|
90
|
-
# checks
|
|
90
|
+
# checks machine OS
|
|
91
91
|
self.__machine_OS = platform.system()
|
|
92
92
|
|
|
93
93
|
# define internal parameters
|
|
@@ -100,9 +100,11 @@ class Sourcer:
|
|
|
100
100
|
|
|
101
101
|
# sanitize sourcer_params
|
|
102
102
|
self.__sourcer_params = {
|
|
103
|
-
str(k).strip():
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
str(k).strip(): (
|
|
104
|
+
str(v).strip()
|
|
105
|
+
if not isinstance(v, (dict, list, int, float, tuple))
|
|
106
|
+
else v
|
|
107
|
+
)
|
|
106
108
|
for k, v in sourcer_params.items()
|
|
107
109
|
}
|
|
108
110
|
|
|
@@ -199,6 +201,7 @@ class Sourcer:
|
|
|
199
201
|
|
|
200
202
|
# various source stream params
|
|
201
203
|
self.__default_video_resolution = "" # handles stream resolution
|
|
204
|
+
self.__default_video_orientation = "" # handles stream's video orientation
|
|
202
205
|
self.__default_video_framerate = "" # handles stream framerate
|
|
203
206
|
self.__default_video_bitrate = "" # handles stream's video bitrate
|
|
204
207
|
self.__default_video_pixfmt = "" # handles stream's video pixfmt
|
|
@@ -218,6 +221,7 @@ class Sourcer:
|
|
|
218
221
|
self.__output_frames_resolution = "" # handles output stream resolution
|
|
219
222
|
self.__output_framerate = "" # handles output stream framerate
|
|
220
223
|
self.__output_frames_pixfmt = "" # handles output frame pixel format
|
|
224
|
+
self.__output_orientation = "" # handles output frame orientation
|
|
221
225
|
|
|
222
226
|
# check whether metadata probed or not?
|
|
223
227
|
self.__metadata_probed = False
|
|
@@ -251,6 +255,7 @@ class Sourcer:
|
|
|
251
255
|
if video_rfparams:
|
|
252
256
|
self.__default_video_resolution = video_rfparams["resolution"]
|
|
253
257
|
self.__default_video_framerate = video_rfparams["framerate"]
|
|
258
|
+
self.__default_video_orientation = video_rfparams["orientation"]
|
|
254
259
|
|
|
255
260
|
# parse output parameters through filters (if available)
|
|
256
261
|
if not (self.__metadata_output is None):
|
|
@@ -261,6 +266,7 @@ class Sourcer:
|
|
|
261
266
|
if out_video_rfparams:
|
|
262
267
|
self.__output_frames_resolution = out_video_rfparams["resolution"]
|
|
263
268
|
self.__output_framerate = out_video_rfparams["framerate"]
|
|
269
|
+
self.__output_orientation = out_video_rfparams["orientation"]
|
|
264
270
|
# parse output pixel-format
|
|
265
271
|
self.__output_frames_pixfmt = self.__extract_video_pixfmt(
|
|
266
272
|
default_stream=default_stream_indexes[0], extract_output=True
|
|
@@ -357,6 +363,7 @@ class Sourcer:
|
|
|
357
363
|
"source_video_resolution": self.__default_video_resolution,
|
|
358
364
|
"source_video_pixfmt": self.__default_video_pixfmt,
|
|
359
365
|
"source_video_framerate": self.__default_video_framerate,
|
|
366
|
+
"source_video_orientation": self.__default_video_orientation,
|
|
360
367
|
"source_video_decoder": self.__default_video_decoder,
|
|
361
368
|
"source_duration_sec": self.__default_source_duration,
|
|
362
369
|
"approx_video_nframes": (
|
|
@@ -385,6 +392,7 @@ class Sourcer:
|
|
|
385
392
|
"output_frames_resolution": self.__output_frames_resolution,
|
|
386
393
|
"output_frames_pixfmt": self.__output_frames_pixfmt,
|
|
387
394
|
"output_framerate": self.__output_framerate,
|
|
395
|
+
"output_orientation": self.__output_orientation,
|
|
388
396
|
}
|
|
389
397
|
)
|
|
390
398
|
else:
|
|
@@ -397,6 +405,7 @@ class Sourcer:
|
|
|
397
405
|
"output_frames_resolution": self.__default_video_resolution,
|
|
398
406
|
"output_frames_pixfmt": self.__default_video_pixfmt,
|
|
399
407
|
"output_framerate": self.__default_video_framerate,
|
|
408
|
+
"output_orientation": self.__default_video_orientation,
|
|
400
409
|
}
|
|
401
410
|
)
|
|
402
411
|
# log it
|
|
@@ -489,14 +498,18 @@ class Sourcer:
|
|
|
489
498
|
self.__source_demuxer = source_demuxer
|
|
490
499
|
self.__verbose_logs and logger.debug(
|
|
491
500
|
"Successfully configured device `{}` at index `{}` with demuxer `{}`.".format(
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
501
|
+
(
|
|
502
|
+
self.__extracted_devices_list[index]
|
|
503
|
+
if self.__machine_OS != "Linux"
|
|
504
|
+
else next(
|
|
505
|
+
iter(self.__extracted_devices_list[index].values())
|
|
506
|
+
)[0]
|
|
507
|
+
),
|
|
508
|
+
(
|
|
509
|
+
index
|
|
510
|
+
if index >= 0
|
|
511
|
+
else len(self.__extracted_devices_list) + index
|
|
512
|
+
),
|
|
500
513
|
self.__source_demuxer,
|
|
501
514
|
)
|
|
502
515
|
)
|
|
@@ -596,9 +609,11 @@ class Sourcer:
|
|
|
596
609
|
]
|
|
597
610
|
if video_bitrate_text:
|
|
598
611
|
selected_stream = video_bitrate_text[
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
612
|
+
(
|
|
613
|
+
default_stream
|
|
614
|
+
if default_stream > 0 and default_stream < len(video_bitrate_text)
|
|
615
|
+
else 0
|
|
616
|
+
)
|
|
602
617
|
]
|
|
603
618
|
filtered_bitrate = re.findall(
|
|
604
619
|
r",\s[0-9]+\s\w\w[\/]s", selected_stream.strip()
|
|
@@ -630,9 +645,11 @@ class Sourcer:
|
|
|
630
645
|
]
|
|
631
646
|
if meta_text:
|
|
632
647
|
selected_stream = meta_text[
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
648
|
+
(
|
|
649
|
+
default_stream
|
|
650
|
+
if default_stream > 0 and default_stream < len(meta_text)
|
|
651
|
+
else 0
|
|
652
|
+
)
|
|
636
653
|
]
|
|
637
654
|
filtered_pixfmt = re.findall(
|
|
638
655
|
r"Video:\s[a-z0-9_-]*", selected_stream.strip()
|
|
@@ -666,9 +683,11 @@ class Sourcer:
|
|
|
666
683
|
)
|
|
667
684
|
if meta_text:
|
|
668
685
|
selected_stream = meta_text[
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
686
|
+
(
|
|
687
|
+
default_stream
|
|
688
|
+
if default_stream > 0 and default_stream < len(meta_text)
|
|
689
|
+
else 0
|
|
690
|
+
)
|
|
672
691
|
]
|
|
673
692
|
filtered_pixfmt = re.findall(
|
|
674
693
|
r",\s[a-z][a-z0-9_-]*", selected_stream.strip()
|
|
@@ -695,9 +714,11 @@ class Sourcer:
|
|
|
695
714
|
result = {}
|
|
696
715
|
if meta_text:
|
|
697
716
|
selected_stream = meta_text[
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
717
|
+
(
|
|
718
|
+
default_stream
|
|
719
|
+
if default_stream > 0 and default_stream < len(meta_text)
|
|
720
|
+
else 0
|
|
721
|
+
)
|
|
701
722
|
]
|
|
702
723
|
# filter data
|
|
703
724
|
filtered_audio_bitrate = re.findall(
|
|
@@ -725,7 +746,7 @@ class Sourcer:
|
|
|
725
746
|
|
|
726
747
|
def __extract_resolution_framerate(self, default_stream=0, extract_output=False):
|
|
727
748
|
"""
|
|
728
|
-
This Internal method parses default video-stream resolution and framerate from metadata.
|
|
749
|
+
This Internal method parses default video-stream resolution, orientation, and framerate from metadata.
|
|
729
750
|
|
|
730
751
|
Parameters:
|
|
731
752
|
default_stream (int): selects specific audio-stream in case of multiple ones.
|
|
@@ -748,12 +769,30 @@ class Sourcer:
|
|
|
748
769
|
if all(x in line for x in identifiers)
|
|
749
770
|
]
|
|
750
771
|
)
|
|
772
|
+
# extract video orientation metadata if available
|
|
773
|
+
identifiers_orientation = ["displaymatrix:", "rotation"]
|
|
774
|
+
meta_text_orientation = (
|
|
775
|
+
[
|
|
776
|
+
line.strip()
|
|
777
|
+
for line in self.__ffsp_output.split("\n")
|
|
778
|
+
if all(x in line for x in identifiers_orientation)
|
|
779
|
+
]
|
|
780
|
+
if not extract_output
|
|
781
|
+
else [
|
|
782
|
+
line.strip()
|
|
783
|
+
for line in self.__metadata_output.split("\n")
|
|
784
|
+
if all(x in line for x in identifiers_orientation)
|
|
785
|
+
]
|
|
786
|
+
)
|
|
787
|
+
# use metadata if available
|
|
751
788
|
result = {}
|
|
752
789
|
if meta_text:
|
|
753
790
|
selected_stream = meta_text[
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
791
|
+
(
|
|
792
|
+
default_stream
|
|
793
|
+
if default_stream > 0 and default_stream < len(meta_text)
|
|
794
|
+
else 0
|
|
795
|
+
)
|
|
757
796
|
]
|
|
758
797
|
|
|
759
798
|
# filter data
|
|
@@ -781,7 +820,23 @@ class Sourcer:
|
|
|
781
820
|
if filtered_resolution:
|
|
782
821
|
result["resolution"] = [int(x) for x in filtered_resolution[0]]
|
|
783
822
|
|
|
784
|
-
|
|
823
|
+
# extract video orientation metadata
|
|
824
|
+
if meta_text_orientation:
|
|
825
|
+
selected_stream = meta_text_orientation[
|
|
826
|
+
(
|
|
827
|
+
default_stream
|
|
828
|
+
if default_stream > 0 and default_stream < len(meta_text)
|
|
829
|
+
else 0
|
|
830
|
+
)
|
|
831
|
+
]
|
|
832
|
+
filtered_orientation = re.findall(
|
|
833
|
+
r"[-]?\d+\.\d+", selected_stream.strip()
|
|
834
|
+
)
|
|
835
|
+
result["orientation"] = float(filtered_orientation[0])
|
|
836
|
+
else:
|
|
837
|
+
result["orientation"] = 0.0
|
|
838
|
+
|
|
839
|
+
return result if result and (len(result) == 3) else {}
|
|
785
840
|
|
|
786
841
|
def __extract_duration(self, inseconds=True):
|
|
787
842
|
"""
|
deffcode/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.2.
|
|
1
|
+
__version__ = "0.2.6"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: deffcode
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.6
|
|
4
4
|
Summary: A cross-platform High-performance & Flexible Real-time Video Frames Decoder in Python.
|
|
5
5
|
Home-page: https://abhitronix.github.io/deffcode
|
|
6
6
|
Author: Abhishek Thakur
|
|
@@ -23,11 +23,11 @@ Classifier: Intended Audience :: Developers
|
|
|
23
23
|
Classifier: Intended Audience :: Science/Research
|
|
24
24
|
Classifier: Intended Audience :: Education
|
|
25
25
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
26
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
27
26
|
Classifier: Programming Language :: Python :: 3.8
|
|
28
27
|
Classifier: Programming Language :: Python :: 3.9
|
|
29
28
|
Classifier: Programming Language :: Python :: 3.10
|
|
30
|
-
|
|
29
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
30
|
+
Requires-Python: >=3.8
|
|
31
31
|
Description-Content-Type: text/markdown
|
|
32
32
|
License-File: LICENSE
|
|
33
33
|
Requires-Dist: cython
|
|
@@ -321,7 +321,7 @@ print(sourcer.retrieve_metadata(pretty_json=True))
|
|
|
321
321
|
|
|
322
322
|
> We're happy to meet new contributors💗
|
|
323
323
|
|
|
324
|
-
We welcome your contributions to help us improve and extend this project. If you want to get involved with
|
|
324
|
+
We welcome your contributions to help us improve and extend this project. If you want to get involved with DeFFcode development, checkout the **[Contribution Guidelines ▶️][contribute]**
|
|
325
325
|
|
|
326
326
|
We're offering support for DeFFcode on [**Gitter Community Channel**][gitter]. Come and join the conversation over there!
|
|
327
327
|
|
|
@@ -348,18 +348,18 @@ It is something I am doing with my own free time. But so much more needs to be d
|
|
|
348
348
|
|
|
349
349
|
Here is a Bibtex entry you can use to cite this project in a publication:
|
|
350
350
|
|
|
351
|
-
[](https://doi.org/10.5281/zenodo.7523792)
|
|
352
352
|
|
|
353
353
|
```BibTeX
|
|
354
354
|
@software{deffcode,
|
|
355
|
-
author = {Abhishek
|
|
356
|
-
title = {abhiTronix/deffcode: v0.2.
|
|
357
|
-
month =
|
|
358
|
-
year =
|
|
355
|
+
author = {Abhishek Thakur},
|
|
356
|
+
title = {abhiTronix/deffcode: v0.2.5},
|
|
357
|
+
month = jan,
|
|
358
|
+
year = 2023,
|
|
359
359
|
publisher = {Zenodo},
|
|
360
|
-
version = {v0.2.
|
|
361
|
-
doi = {10.5281/zenodo.
|
|
362
|
-
url = {https://doi.org/10.5281/zenodo.
|
|
360
|
+
version = {v0.2.5},
|
|
361
|
+
doi = {10.5281/zenodo.7523792},
|
|
362
|
+
url = {https://doi.org/10.5281/zenodo.7523792}
|
|
363
363
|
}
|
|
364
364
|
```
|
|
365
365
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
deffcode/__init__.py,sha256=_WZUSTOnxtJLMQV7Bb70AyVPhfmhWf1OKOHbQhBaWzk,291
|
|
2
|
+
deffcode/ffdecoder.py,sha256=0JeDH7of9ovrdGOwYWYzyCPiOGDBS_UBXxD5DySjPOY,42988
|
|
3
|
+
deffcode/ffhelper.py,sha256=ReXn3zEkLY3VqhJlMmZATD5DDU-ad5auZ6q_oZ80E04,26821
|
|
4
|
+
deffcode/sourcer.py,sha256=T8eKJReox3jNPA8YTC7mZVzy4ZQgMzHvKuCMkqUjBqs,38110
|
|
5
|
+
deffcode/utils.py,sha256=LUnKF0MB9E02gK3CXccUVFBsHn6l8RRS5SzvV7SFySI,4929
|
|
6
|
+
deffcode/version.py,sha256=-PlEVSVU0gTlP_wD3xffzA9LlqJQ7GGQdBSP6mKnDvY,23
|
|
7
|
+
deffcode-0.2.6.dist-info/LICENSE,sha256=mBL-N_pLsrkx4_Ix9NCN51pxCeYcLpnTeTsj-18ub5I,12479
|
|
8
|
+
deffcode-0.2.6.dist-info/METADATA,sha256=-VfGa3dmH7FM495lsPl0YWKGPIakNwByXrb8457QRRE,33237
|
|
9
|
+
deffcode-0.2.6.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
10
|
+
deffcode-0.2.6.dist-info/top_level.txt,sha256=1C-kyZgIKFviemaQMmhP0VKR3wkzEZcrf1o5oUckvHI,9
|
|
11
|
+
deffcode-0.2.6.dist-info/RECORD,,
|
deffcode-0.2.5.dist-info/RECORD
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
deffcode/__init__.py,sha256=_WZUSTOnxtJLMQV7Bb70AyVPhfmhWf1OKOHbQhBaWzk,291
|
|
2
|
-
deffcode/ffdecoder.py,sha256=BcaxyQFswfLBiLfSCsYyZRTS7ka7RGnGEiB1CEBqEGw,41385
|
|
3
|
-
deffcode/ffhelper.py,sha256=Gzyo8eHu7J6GVnVYVs2-GIxHeSd3AVy2id-N8LbhgwE,26563
|
|
4
|
-
deffcode/sourcer.py,sha256=0iUD8nLVp3F8UnlFpm_wFtSz-ClHFiMtV1XQygW_04s,35874
|
|
5
|
-
deffcode/utils.py,sha256=LUnKF0MB9E02gK3CXccUVFBsHn6l8RRS5SzvV7SFySI,4929
|
|
6
|
-
deffcode/version.py,sha256=UrVWe9Q1Se9JzaYR6i-dvrfP7NV-jHi9kYGFTTlf00g,23
|
|
7
|
-
deffcode-0.2.5.dist-info/LICENSE,sha256=mBL-N_pLsrkx4_Ix9NCN51pxCeYcLpnTeTsj-18ub5I,12479
|
|
8
|
-
deffcode-0.2.5.dist-info/METADATA,sha256=QkiJMM83wEGE_nUgIX_OxS5C9GLQdkC5B9MDQ3q8lXM,33241
|
|
9
|
-
deffcode-0.2.5.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
|
10
|
-
deffcode-0.2.5.dist-info/top_level.txt,sha256=1C-kyZgIKFviemaQMmhP0VKR3wkzEZcrf1o5oUckvHI,9
|
|
11
|
-
deffcode-0.2.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|