/** @internal @This gets or allocates the current item. * * @param upipe description structure of the pipe * @param flow_def the current flow definition * @param item_p pointer to the item * @return an error code */ static int upipe_m3u_reader_get_item(struct upipe *upipe, struct uref *flow_def, struct uref **item_p) { struct upipe_m3u_reader *upipe_m3u_reader = upipe_m3u_reader_from_upipe(upipe); if (unlikely(item_p == NULL) || unlikely(flow_def == NULL)) return UBASE_ERR_INVALID; if (unlikely(upipe_m3u_reader->item == NULL)) { upipe_m3u_reader->item = uref_sibling_alloc_control(flow_def); if (unlikely(upipe_m3u_reader->item == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } } *item_p = upipe_m3u_reader->item; return UBASE_ERR_NONE; }
/** @internal @This iterates the variant. * * @param upipe description structure of the pipe * @param uref_p filled with the next variant or NULL * @return an error code */ static int upipe_hls_split_iterate(struct upipe *upipe, struct uref **uref_p) { struct upipe_hls *upipe_hls = upipe_hls_from_upipe(upipe); if (!uref_p) return UBASE_ERR_INVALID; if (!upipe_hls->flow_def) return UBASE_ERR_INVALID; const char *def = NULL; uref_flow_get_def(upipe_hls->flow_def, &def); if (!def) return UBASE_ERR_INVALID; if (!strcmp(def, "block.m3u.master.")) return upipe_split_iterate(upipe_hls->last_inner, uref_p); if (*uref_p) { *uref_p = NULL; } else { if (!upipe_hls->item) { struct uref *item = uref_sibling_alloc_control(upipe_hls->flow_def); if (unlikely(!item)) return UBASE_ERR_ALLOC; uref_flow_set_id(item, 1); char *uri = NULL; uref_uri_get_to_str(upipe_hls->flow_def, &uri); uref_m3u_set_uri(item, uri); free(uri); upipe_hls->item = item; } *uref_p = upipe_hls->item; } return UBASE_ERR_NONE; }
static int upipe_m3u_reader_key(struct upipe *upipe, struct uref *flow_def, const char *line) { struct upipe_m3u_reader *upipe_m3u_reader = upipe_m3u_reader_from_upipe(upipe); if (unlikely(!ubase_check(uref_flow_match_def(flow_def, M3U_FLOW_DEF))) && unlikely(!ubase_check(uref_flow_match_def(flow_def, PLAYLIST_FLOW_DEF)))) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_set_def(flow_def, PLAYLIST_FLOW_DEF)); struct uref *key = uref_sibling_alloc_control(flow_def); if (unlikely(key == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } if (upipe_m3u_reader->key) uref_free(upipe_m3u_reader->key); upipe_m3u_reader->key = key; const char *iterator = line; struct ustring name, value; while (ubase_check(attribute_iterate(&iterator, &name, &value)) && iterator != NULL) { char value_str[value.len + 1]; int err = ustring_cpy(value, value_str, sizeof (value_str)); if (unlikely(!ubase_check(err))) { upipe_err_va(upipe, "fail to copy ustring %.*s", (int)value.len, value.at); continue; } if (!ustring_cmp_str(name, "METHOD")) { err = uref_m3u_playlist_key_set_method(key, value_str); if (unlikely(!ubase_check(err))) upipe_err_va(upipe, "fail to set key method to %s", value_str); } else if (!ustring_cmp_str(name, "URI")) { err = uref_m3u_playlist_key_set_uri(key, value_str); if (unlikely(!ubase_check(err))) upipe_err_va(upipe, "fail to set uri to %s", value_str); } else if (!ustring_cmp_str(name, "IV")) { size_t len = strlen(value_str); if (unlikely(len > 32)) { upipe_warn_va(upipe, "invalid initialization vector %s", value_str); continue; } for (unsigned i = 0; i < len; i += 2) { if (unlikely(!isxdigit(value_str[i])) || unlikely(!isxdigit(value_str[i + 1]))) { upipe_warn_va(upipe, "invalid initialization vector %s", value_str); continue; } //FIXME //iv[] = value_str[i] } } else { upipe_warn_va(upipe, "ignoring attribute %.*s (%.*s)", (int)name.len, name.at, (int)value.len, value.at); } } return UBASE_ERR_NONE; }
static int upipe_m3u_reader_process_media(struct upipe *upipe, struct uref *flow_def, const char *line) { struct upipe_m3u_reader *upipe_m3u_reader = upipe_m3u_reader_from_upipe(upipe); if (!ubase_check(uref_flow_match_def(flow_def, M3U_FLOW_DEF)) && !ubase_check(uref_flow_match_def(flow_def, MASTER_FLOW_DEF))) return UBASE_ERR_INVALID; UBASE_RETURN(uref_flow_set_def(flow_def, MASTER_FLOW_DEF)); struct uref *item = uref_sibling_alloc_control(flow_def); if (unlikely(item == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return UBASE_ERR_ALLOC; } struct ustring name, value; while (ubase_check(attribute_iterate(&line, &name, &value)) && line) { if (!ustring_cmp_str(name, "URI")) { value = ustring_unframe(value, '"'); char val[value.len + 1]; int err = ustring_cpy(value, val, sizeof (val)); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to copy %.*s", (int)value.len, value.at); continue; } err = uref_m3u_set_uri(item, val); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to set uri %s", val); continue; } } else if (!ustring_cmp_str(name, "TYPE")) { char val[value.len + 1]; int err = ustring_cpy(value, val, sizeof (val)); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to copy %.*s", (int)value.len, value.at); continue; } err = uref_m3u_master_set_media_type(item, val); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to set media type %s", val); continue; } } else if (!ustring_cmp_str(name, "DEFAULT")) { if (!ustring_cmp_str(value, "YES")) { int err = uref_m3u_master_set_media_default(item); if (unlikely(!ubase_check(err))) continue; } else if (ustring_cmp_str(value, "NO")) { upipe_warn_va(upipe, "invalid DEFAULT value %.*s", (int)value.len, value.at); continue; } } else if (!ustring_cmp_str(name, "AUTOSELECT")) { if (!ustring_cmp_str(value, "YES")) { int err = uref_m3u_master_set_media_autoselect(item); if (unlikely(!ubase_check(err))) continue; } else if (ustring_cmp_str(value, "NO")) { upipe_warn_va(upipe, "invalid AUTOSELECT value %.*s", (int)value.len, value.at); continue; } } else if (!ustring_cmp_str(name, "NAME")) { value = ustring_unframe(value, '"'); char val[value.len + 1]; int err = ustring_cpy(value, val, sizeof (val)); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to copy %.*s", (int)value.len, value.at); continue; } err = uref_m3u_master_set_media_name(item, val); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to set media name %s", val); continue; } } else if (!ustring_cmp_str(name, "GROUP-ID")) { value = ustring_unframe(value, '"'); char val[value.len + 1]; int err = ustring_cpy(value, val, sizeof (val)); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to copy %.*s", (int)value.len, value.at); continue; } err = uref_m3u_master_set_media_group(item, val); if (unlikely(!ubase_check(err))) { upipe_warn_va(upipe, "fail to set group id %s", val); continue; } } else { upipe_warn_va(upipe, "ignoring attribute %.*s (%.*s)", (int)name.len, name.at, (int)value.len, value.at); } } ulist_add(&upipe_m3u_reader->items, uref_to_uchain(item)); return UBASE_ERR_NONE; }