Skip to content

Commit 55b28ae

Browse files
committed
Initial commit
1 parent a155e6f commit 55b28ae

File tree

5 files changed

+334
-3
lines changed

5 files changed

+334
-3
lines changed

src/cpython/kai/kai.py src/cpython/kai/__kai.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
m3u8stream_init,
33
m3u8stream_load,
44
m3u8stream_load_url,
5-
m3u8stream_load_file
5+
m3u8stream_load_file,
6+
m3u8stream_getstream
67
)
78

89
from exceptions import code2exception, KaiErrorCode
@@ -30,6 +31,8 @@ def load(self, something, base_url = None):
3031

3132
self.ensure_non_error()
3233

34+
return m3u8stream_getstream(self.instance)
35+
3336
return self
3437

3538
def load_url(self, url, base_url = None):
@@ -55,4 +58,5 @@ def load_file(self, filename, base_url = None):
5558
return self
5659

5760
stream = M3U8Stream()
58-
stream.load_url("https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8")
61+
a=stream.load("/storage/emulated/0/cq3l8ci23aks73akgsug/master.m3u8")
62+
print(a.__dict__)

src/cpython/kai/types/__init__.py src/cpython/kai/_types/__init__.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
M3U8VariantStream
2424
)
2525

26+
from .m3u8 import (
27+
M3U8Resolution
28+
)
29+
30+
2631
__all__ = [
2732
"M3U8MediaType",
2833
"M3U8ClosedCaption",
@@ -45,5 +50,6 @@
4550
"M3U8SessionData",
4651
"M3U8Start",
4752
"M3U8Media",
48-
"M3U8VariantStream"
53+
"M3U8VariantStream",
54+
"M3U8Resolution"
4955
]

src/cpython/kai/_types/m3u8.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class M3U8Resolution:
2+
3+
def __init__(self, width, height):
4+
self.width = width
5+
self.height = height
File renamed without changes.

src/python-kai.c

+316
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,316 @@ static PyObject* _m3u8stream_load_file(
267267

268268
}
269269

270+
static PyObject* get_string(const char* const value) {
271+
272+
if (value == NULL) {
273+
return Py_None;
274+
}
275+
276+
return PyUnicode_FromString(value);
277+
278+
}
279+
280+
static PyObject* get_enum(const char* const name, const biguint_t value) {
281+
282+
PyObject* result = NULL;
283+
284+
PyObject* arg = NULL;
285+
PyObject* args = NULL;
286+
287+
PyObject* class = NULL;
288+
PyObject* module = PyImport_ImportModule("kai");
289+
290+
if (module == NULL) {
291+
goto end;
292+
}
293+
294+
class = PyObject_GetAttrString(module, name);
295+
296+
if (class == NULL) {
297+
goto end;
298+
}
299+
300+
arg = PyLong_FromLongLong(value);
301+
302+
if (arg == NULL) {
303+
goto end;
304+
}
305+
306+
args = Py_BuildValue("(O)", arg);
307+
308+
if (args == NULL) {
309+
goto end;
310+
}
311+
312+
result = PyObject_Call(class, args, NULL);
313+
314+
if (result == NULL) {
315+
goto end;
316+
}
317+
318+
end:;
319+
320+
Py_XDECREF(module);
321+
Py_XDECREF(class);
322+
Py_XDECREF(arg);
323+
Py_XDECREF(args);
324+
325+
return result;
326+
327+
}
328+
329+
static PyObject* topy(const void* const object, const enum M3U8StreamItemType ktype) {
330+
331+
PyObject* args = NULL;
332+
333+
PyObject* type = NULL;
334+
PyObject* uri = NULL;
335+
PyObject* group_id = NULL;
336+
PyObject* language = NULL;
337+
PyObject* assoc_language = NULL;
338+
PyObject* name = NULL;
339+
PyObject* _default = NULL;
340+
PyObject* autoselect = NULL;
341+
PyObject* forced = NULL;
342+
PyObject* instream_id = NULL;
343+
PyObject* characteristics = NULL;
344+
PyObject* channels = NULL;
345+
PyObject* stream = NULL;
346+
PyObject* duration = NULL;
347+
PyObject* average_duration = NULL;
348+
PyObject* segments = NULL;
349+
PyObject* tag = NULL;
350+
351+
PyObject* result = NULL;
352+
PyObject* kwargs = NULL;
353+
354+
PyObject* class = NULL;
355+
356+
PyObject* module = NULL;
357+
358+
module = PyImport_ImportModule("kai");
359+
360+
if (module == NULL) {
361+
return NULL;
362+
}
363+
364+
switch (ktype) {
365+
case M3U8_STREAM_MEDIA: {
366+
const struct M3U8Media* const media = object;
367+
368+
/* Type */
369+
type = get_enum("M3U8MediaType", media->type);
370+
371+
if (type == NULL) {
372+
return NULL;
373+
}
374+
375+
/* URI */
376+
uri = get_string(media->uri);
377+
378+
if (uri == NULL) {
379+
return NULL;
380+
}
381+
382+
/* Group ID */
383+
group_id = get_string(media->group_id);
384+
385+
if (group_id == NULL) {
386+
return NULL;
387+
}
388+
389+
/* Language */
390+
language = get_string(media->language);
391+
392+
if (language == NULL) {
393+
return NULL;
394+
}
395+
396+
/* Associated language */
397+
assoc_language = get_string(media->assoc_language);
398+
399+
if (assoc_language == NULL) {
400+
return NULL;
401+
}
402+
403+
/* Name */
404+
name = get_string(media->name);
405+
406+
if (name == NULL) {
407+
return NULL;
408+
}
409+
410+
/* Default */
411+
_default = PyBool_FromLong(media->default_);
412+
413+
/* Autoselect */
414+
autoselect = PyBool_FromLong(media->autoselect);
415+
416+
/* Forced */
417+
forced = PyBool_FromLong(media->forced);
418+
419+
/* InStream ID */
420+
instream_id = get_enum("M3U8ClosedCaption", media->instream_id);
421+
422+
if (instream_id == NULL) {
423+
return NULL;
424+
}
425+
426+
/* Characteristics */
427+
characteristics = get_string(media->characteristics);
428+
429+
if (characteristics == NULL) {
430+
return NULL;
431+
}
432+
433+
/* Channels */
434+
channels = get_string(media->channels);
435+
436+
if (channels == NULL) {
437+
return NULL;
438+
}
439+
440+
/* Stream */
441+
stream = Py_None;
442+
443+
/* Duration */
444+
duration = PyLong_FromLongLong(media->duration);
445+
446+
if (duration == NULL) {
447+
return NULL;
448+
}
449+
450+
/* Average duration */
451+
average_duration = PyLong_FromLongLong(media->average_duration);
452+
453+
if (average_duration == NULL) {
454+
return NULL;
455+
}
456+
457+
average_duration = PyLong_FromLongLong(media->average_duration);
458+
459+
if (average_duration == NULL) {
460+
return NULL;
461+
}
462+
463+
/* Segments */
464+
segments = PyLong_FromLongLong(media->segments);
465+
466+
if (segments == NULL) {
467+
return NULL;
468+
}
469+
470+
/* Tag */
471+
tag = PyLong_FromLongLong((uintptr_t) media->tag);
472+
473+
if (tag == NULL) {
474+
return NULL;
475+
}
476+
477+
args = Py_BuildValue(
478+
"(OOOOOOOOOOOOOOOOO)",
479+
type,
480+
uri,
481+
group_id,
482+
language,
483+
assoc_language,
484+
name,
485+
_default,
486+
autoselect,
487+
forced,
488+
instream_id,
489+
characteristics,
490+
channels,
491+
stream,
492+
duration,
493+
average_duration,
494+
segments,
495+
tag
496+
);
497+
498+
if (args == NULL) {
499+
return NULL;
500+
}
501+
502+
class = PyObject_GetAttrString(module, "M3U8Media");
503+
504+
if (class == NULL) {
505+
return NULL;
506+
}
507+
508+
result = PyObject_Call(class, args, kwargs);
509+
510+
break;
511+
}
512+
}
513+
514+
Py_DECREF(module);
515+
Py_DECREF(class);
516+
517+
return result;
518+
519+
}
520+
521+
static PyObject* _m3u8stream_getstream(
522+
PyObject* self,
523+
PyObject* args
524+
) {
525+
526+
size_t index = 0;
527+
528+
int err = M3U8ERR_SUCCESS;
529+
530+
struct M3U8Stream* stream = NULL;
531+
532+
PyObject* items = NULL;
533+
PyObject* module = NULL;
534+
535+
unsigned long long pointer = 0;
536+
537+
if (!PyArg_ParseTuple(args, "K", &pointer)) {
538+
return NULL;
539+
}
540+
541+
stream = (struct M3U8Stream*) pointer;
542+
543+
items = PyList_New(0);
544+
545+
if (items == NULL) {
546+
return NULL;
547+
}
548+
549+
module = PyImport_ImportModule("kai");
550+
551+
if (module == NULL) {
552+
return NULL;
553+
}
554+
555+
for (index = 0; index < stream->offset; index++) {
556+
const struct M3U8StreamItem* const item = &stream->items[index];
557+
558+
switch (item->type) {
559+
case M3U8_STREAM_MEDIA: {
560+
return topy(item->item, item->type);
561+
}
562+
case M3U8_STREAM_VARIANT_STREAM: {
563+
const struct M3U8VariantStream* const variant = item->item;
564+
/*
565+
PyObject* variant_stream = PyObject_GetAttrString(module, "M3U8VariantStream"):
566+
PyObject* resolution = PyObject_GetAttrString(module, "M3U8Resolution"):
567+
568+
PyObject* bandwidth = PyLong_FromLongLong(variant_stream->bandwidth);
569+
PyObject* average_bandwidth = PyLong_FromLongLong(variant_stream->average_bandwidth);
570+
PyObject* program_id = PyLong_FromLongLong(variant_stream->program_id);
571+
PyObject* codecs = PyUnicode_FromString(variant_stream->codecs);
572+
*/
573+
break;
574+
}
575+
}
576+
}
577+
578+
}
579+
270580
static PyMethodDef methods[] = {
271581
{
272582
"m3u8stream_init",
@@ -292,6 +602,12 @@ static PyMethodDef methods[] = {
292602
METH_VARARGS,
293603
"Execute a shell command."
294604
},
605+
{
606+
"m3u8stream_getstream",
607+
_m3u8stream_getstream,
608+
METH_VARARGS,
609+
"Execute a shell command."
610+
},
295611
{NULL, NULL, 0, NULL} /* Sentinel */
296612
};
297613

0 commit comments

Comments
 (0)