Exemplo n.º 1
0
static int parse_playlist(HLSContext *c, const char *url,
                          struct variant *var, AVIOContext *in)
{
    int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
    enum KeyType key_type = KEY_NONE;
    uint8_t iv[16] = "";
    int has_iv = 0;
    char key[MAX_URL_SIZE] = "";
    char line[1024];
    const char *ptr;
    int close_in = 0;

    if (!in) {
        int is_redirected = 0;
        URLContext *h = NULL;
        AVDictionary *opts = NULL;
        close_in = 1;
        /* Some HLS servers dont like being sent the range header */
        av_dict_set(&opts, "seekable", "0", 0);
        ret = avio_open2(&in, url, AVIO_FLAG_READ,
                         c->interrupt_callback, &opts);
        av_dict_free(&opts);
        if (ret < 0)
            return ret;

        h = (URLContext *) in->opaque;
        ff_http_get_location_changed(h, &is_redirected);
        if ( is_redirected ) {
           ff_http_get_new_location(h, var->url);
           av_log(NULL, AV_LOG_WARNING, "the var url changed to %s \n", var->url);
        }
    }

    read_chomp_line(in, line, sizeof(line));
    if (strcmp(line, "#EXTM3U")) {
        ret = AVERROR_INVALIDDATA;
        goto fail;
    }

    if (var) {
        free_segment_list(var);
        var->finished = 0;
    }
    while (!url_feof(in)) {
        read_chomp_line(in, line, sizeof(line));
        if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
            struct variant_info info = {{0}};
            is_variant = 1;
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
                               &info);
            bandwidth = atoi(info.bandwidth);
        } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {
            struct key_info info = {{0}};
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
                               &info);
            key_type = KEY_NONE;
            has_iv = 0;
            if (!strcmp(info.method, "AES-128"))
                key_type = KEY_AES_128;
            if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
                ff_hex_to_data(iv, info.iv + 2);
                has_iv = 1;
            }
            av_strlcpy(key, info.uri, sizeof(key));
        } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
            if (!var) {
                var = new_variant(c, 0, url, NULL);
                if (!var) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
            }
            var->target_duration = atoi(ptr);
        } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
            if (!var) {
                var = new_variant(c, 0, url, NULL);
                if (!var) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
            }
            var->start_seq_no = atoi(ptr);
        } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
            if (var)
                var->finished = 1;
        } else if (av_strstart(line, "#EXTINF:", &ptr)) {
            is_segment = 1;
            duration   = atoi(ptr);
        } else if (av_strstart(line, "#", NULL)) {
            continue;
        } else if (line[0]) {
            if (is_variant) {
                if (!new_variant(c, bandwidth, line, url)) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                is_variant = 0;
                bandwidth  = 0;
            }
            if (is_segment) {
                struct segment *seg;
                if (!var) {
                    var = new_variant(c, 0, url, NULL);
                    if (!var) {
                        ret = AVERROR(ENOMEM);
                        goto fail;
                    }
                }
                seg = av_malloc(sizeof(struct segment));
                if (!seg) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                seg->duration = duration;
                seg->key_type = key_type;
                if (has_iv) {
                    memcpy(seg->iv, iv, sizeof(iv));
                } else {
                    int seq = var->start_seq_no + var->n_segments;
                    memset(seg->iv, 0, sizeof(seg->iv));
                    AV_WB32(seg->iv + 12, seq);
                }
                ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);
                ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);
                dynarray_add(&var->segments, &var->n_segments, seg);
                is_segment = 0;
            }
        }
    }
    if (var)
        var->last_load_time = av_gettime();

fail:
    if (close_in)
        avio_close(in);
    return ret;
}
Exemplo n.º 2
0
static int m3u_parser_line(struct list_mgt *mgt,unsigned char *line,struct list_item*item)
{
    unsigned char *p=line;
    int enditem=0;
    const char* ptr = NULL;
    int isLetvFlag = 0;
    while(*p==' ' && p!='\0' && p-line<1024) p++;
    if(*p!='#' && strlen(p)>0&&mgt->is_variant==0)
    {
        item->file=p;
        enditem=1;
    } else if(av_strstart(line,EXT_LETV_VER, &ptr)) {
        av_log(NULL,AV_LOG_INFO,"Get letv version: %s\n",ptr+1);
        mgt->flags|=IGNORE_SEQUENCE_FLAG;
    } else if(is_TAG(p,EXT_X_ENDLIST)) {
        item->flags|=ENDLIST_FLAG;
        enditem=1;
    } else if(is_TAG(p,EXTINF)) {
        double duration=0.00;
        parseDouble(p+8,&duration);
        av_log(NULL,AV_LOG_INFO,"Get item duration:%.4lf\n",duration);
        //sscanf(p+8,"%d",&duration);//skip strlen("#EXTINF:")
        if(duration>0) {
            item->flags|=DURATION_FLAG;
            item->duration=duration;
        }
    } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
        mgt->target_duration = atoi(ptr);
        av_log(NULL, AV_LOG_INFO, "get target duration:%ld\n",mgt->target_duration);
    } else if(is_TAG(p,EXT_X_ALLOW_CACHE)) {
        item->flags|=ALLOW_CACHE_FLAG;
    } else if(is_TAG(p,EXT_X_MEDIA_SEQUENCE)&&!(mgt->flags&IGNORE_SEQUENCE_FLAG)) {
        int seq = -1;
        int ret=0;
        int slen = strlen("#EXT-X-MEDIA-SEQUENCE:");
        ret=sscanf(p+slen,"%d",&seq); //skip strlen("#EXT-X-MEDIA-SEQUENCE:");
        if(ret>0&&seq>=0&&seq>=mgt->next_seq) {
            if(mgt->start_seq<0) {
                mgt->start_seq=seq;
                if(seq>0) {
                    mgt->flags |=REAL_STREAMING_FLAG;

                }
            }
            item->seq=seq;
            mgt->next_seq=seq+1;

        } else {
            item->seq = seq;
            item->flags|=INVALID_ITEM_FLAG;
        }
    }

    else if(av_strstart(p,"#EXT-X-STREAM-INF:",&ptr)) {
        struct variant_info info = {{0}};
        ff_parse_key_value(p, (ff_parse_key_val_cb) handle_variant_args,
                           &info);
        mgt->bandwidth = atoi(info.bandwidth);
        av_log(NULL, AV_LOG_INFO, "get a stream info,bandwidth:%d\n",mgt->bandwidth);
        mgt->is_variant = 1;
        return -(TRICK_LOGIC_BASE+1);
    }

    else if(av_strstart(p,"#EXT-X-KEY:",&ptr)) {

        struct key_info info = {{0}};
        uint8_t iv[16] = "";
        ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
                           &info);
#if 0
        av_log(NULL,AV_LOG_INFO,"==========start dump a aes key===========\n");
        av_log(NULL,AV_LOG_INFO,"==========key location : %s\n",info.uri);
        av_log(NULL,AV_LOG_INFO,"==========key iv : %s\n",info.iv);
        av_log(NULL,AV_LOG_INFO,"==========key method : %s\n",info.method);
        av_log(NULL,AV_LOG_INFO,"==========end dump a aes key===========\n");

#endif
        struct encrypt_key_priv_t* key_priv_info = av_mallocz(sizeof(struct encrypt_key_priv_t));

        if(NULL == key_priv_info) {
            av_log(NULL,AV_LOG_ERROR,"no memory for key_info\n");
            return -1;
        }

        if(NULL!=mgt->key_tmp) {
            av_log(NULL,AV_LOG_INFO,"released old key info\n");
            av_free(mgt->key_tmp);
            mgt->key_tmp = NULL;
        }

        enum KeyType key_type = KEY_NONE;
        if (!strcmp(info.method, "AES-128")) {
            key_type = KEY_AES_128;

        }
        if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
            ff_hex_to_data(iv, info.iv + 2);
            mgt->has_iv = 1;
        } else {
            mgt->has_iv = 0;
        }
        if(key_type ==KEY_AES_128) {
            key_priv_info->key_type = key_type;
            if(mgt->has_iv>0) {
                memcpy(key_priv_info->iv,iv,sizeof(key_priv_info->iv));
            }

            memcpy(key_priv_info->key_from, "s", 1);
            memcpy(key_priv_info->key_from+1, info.uri, MAX_URL_SIZE-1);

            av_log(NULL,AV_LOG_INFO,"aes key location,before:%s,after:%s\n",info.uri,key_priv_info->key_from);
            key_priv_info->is_have_key_file = 0;
            mgt->key_tmp = key_priv_info;
            mgt->flags |= KEY_FLAG;
            return -(TRICK_LOGIC_BASE+0);

        } else {
            av_log(NULL,AV_LOG_INFO,"just only support aes key\n");
            av_free(key_priv_info);
            key_priv_info = NULL;
        }


    }
    else {

        if(mgt->is_variant>0) {
            if(av_strstart(p,"http",&ptr)) {
                if (!new_variant(mgt, mgt->bandwidth, p, NULL)) {
                    free_variant_list(mgt);
                    return -1;
                }

            } else {
                if (!new_variant(mgt, mgt->bandwidth, p, mgt->prefix)) {
                    free_variant_list(mgt);
                    return -1;
                }
            }
            mgt->is_variant = 0;
            mgt->bandwidth  = 0;

            return -(TRICK_LOGIC_BASE+2);

        }

        return 0;
    }
    return enditem;
}
Exemplo n.º 3
0
Arquivo: hls.c Projeto: lihp1603/libav
static int parse_playlist(HLSContext *c, const char *url,
                          struct variant *var, AVIOContext *in)
{
    int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
    int64_t duration = 0;
    enum KeyType key_type = KEY_NONE;
    uint8_t iv[16] = "";
    int has_iv = 0;
    char key[MAX_URL_SIZE] = "";
    char line[1024];
    const char *ptr;
    int close_in = 0;
    uint8_t *new_url = NULL;

    if (!in) {
        ret = open_in(c, &in, url);
        if (ret < 0)
            return ret;
        close_in = 1;
    }

    if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0)
        url = new_url;

    read_chomp_line(in, line, sizeof(line));
    if (strcmp(line, "#EXTM3U")) {
        ret = AVERROR_INVALIDDATA;
        goto fail;
    }

    if (var) {
        free_segment_list(var);
        var->finished = 0;
    }
    while (!in->eof_reached) {
        read_chomp_line(in, line, sizeof(line));
        if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
            struct variant_info info = {{0}};
            is_variant = 1;
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
                               &info);
            bandwidth = atoi(info.bandwidth);
        } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {
            struct key_info info = {{0}};
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
                               &info);
            key_type = KEY_NONE;
            has_iv = 0;
            if (!strcmp(info.method, "AES-128"))
                key_type = KEY_AES_128;
            if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
                ff_hex_to_data(iv, info.iv + 2);
                has_iv = 1;
            }
            av_strlcpy(key, info.uri, sizeof(key));
        } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
            if (!var) {
                var = new_variant(c, 0, url, NULL);
                if (!var) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
            }
            var->target_duration = atoi(ptr) * AV_TIME_BASE;
        } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
            if (!var) {
                var = new_variant(c, 0, url, NULL);
                if (!var) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
            }
            var->start_seq_no = atoi(ptr);
        } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
            if (var)
                var->finished = 1;
        } else if (av_strstart(line, "#EXTINF:", &ptr)) {
            is_segment = 1;
            duration   = atof(ptr) * AV_TIME_BASE;
        } else if (av_strstart(line, "#", NULL)) {
            continue;
        } else if (line[0]) {
            if (is_variant) {
                if (!new_variant(c, bandwidth, line, url)) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                is_variant = 0;
                bandwidth  = 0;
            }
            if (is_segment) {
                struct segment *seg;
                if (!var) {
                    var = new_variant(c, 0, url, NULL);
                    if (!var) {
                        ret = AVERROR(ENOMEM);
                        goto fail;
                    }
                }
                seg = av_malloc(sizeof(struct segment));
                if (!seg) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                seg->duration = duration;
                seg->key_type = key_type;
                if (has_iv) {
                    memcpy(seg->iv, iv, sizeof(iv));
                } else {
                    int seq = var->start_seq_no + var->n_segments;
                    memset(seg->iv, 0, sizeof(seg->iv));
                    AV_WB32(seg->iv + 12, seq);
                }
                ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);
                ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);
                dynarray_add(&var->segments, &var->n_segments, seg);
                is_segment = 0;
            }
        }
    }
    if (var)
        var->last_load_time = av_gettime_relative();

fail:
    av_free(new_url);
    if (close_in)
        avio_close(in);
    return ret;
}
Exemplo n.º 4
0
static int m3u_parser_line(struct list_mgt *mgt,unsigned char *line,struct list_item*item)
{
	unsigned char *p=line; 
	int enditem=0;
	const char* ptr = NULL;		
	while(*p==' ' && p!='\0' && p-line<1024) p++;
	if(*p!='#' && strlen(p)>0)
	{

		item->file=p; 
		enditem=1;
	}else if(is_TAG(p,EXT_X_ENDLIST)){
		item->flags=ENDLIST_FLAG;
		enditem=1;
	}else if(is_TAG(p,EXTINF)){
		int duration=0;
		sscanf(p+8,"%d",&duration);//skip strlen("#EXTINF:")
		if(duration>0){
			item->flags|=DURATION_FLAG;
			item->duration=duration;
			
		}
	}else if(is_TAG(p,EXT_X_ALLOW_CACHE)){
		item->flags|=ALLOW_CACHE_FLAG;
	}else if(is_TAG(p,EXT_X_MEDIA_SEQUENCE)){
		int seq = -1;
		int slen = strlen("#EXT-X-MEDIA-SEQUENCE:");
		sscanf(p+slen,"%d",&seq); //skip strlen("#EXT-X-MEDIA-SEQUENCE:");	
		if(seq>0){
			if(seq>mgt->seq){
				mgt->seq = seq;
			mgt->flags |=REAL_STREAMING_FLAG;
			av_log(NULL, AV_LOG_INFO, "get new sequence number:%ld\n",seq);
			}else{
				//av_log(NULL, AV_LOG_INFO, "drop this list,sequence number:%ld\n",seq);
				return 0;

			}
			
		}else{
			mgt->seq = seq;
			av_log(NULL, AV_LOG_INFO, "get a invalid sequence number:%d\n",seq);

		}
	}
	
	else if(is_TAG(p,EXT_X_STREAM_INF)){
		struct variant_info info = {{0}};           
		ff_parse_key_value(p, (ff_parse_key_val_cb) handle_variant_args,
		           &info);
		mgt->bandwidth = atoi(info.bandwidth);		
		av_log(NULL, AV_LOG_INFO, "get a stream info,bandwidth:%d\n",mgt->bandwidth);		
		mgt->is_variant = 1;
		return -(TRICK_LOGIC_BASE+1);
	}
	
	else if(av_strstart(p,"#EXT-X-KEY:",&ptr)){
		
		struct key_info info = {{0}};
		uint8_t iv[16] = "";
		ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
		                   &info);
		av_log(NULL,AV_LOG_INFO,"==========start dump a aes key===========\n");
		av_log(NULL,AV_LOG_INFO,"==========key location : %s\n",info.uri);
		av_log(NULL,AV_LOG_INFO,"==========key iv : %s\n",info.iv);
		av_log(NULL,AV_LOG_INFO,"==========key method : %s\n",info.method);
		av_log(NULL,AV_LOG_INFO,"==========end dump a aes key===========\n");
		struct encrypt_key_priv_t* key_priv_info = av_mallocz(sizeof(struct encrypt_key_priv_t));
		if(NULL == key_priv_info){
			av_log(NULL,AV_LOG_ERROR,"no memory for key_info\n");
			return -1;
		}		

		if(NULL!=mgt->key_tmp){
			av_log(NULL,AV_LOG_INFO,"released old key info\n");
			av_free(mgt->key_tmp);
			mgt->key_tmp = NULL;
		}
		
		enum KeyType key_type = KEY_NONE;
		if (!strcmp(info.method, "AES-128")){
		    	key_type = KEY_AES_128;
			
		}
		if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
			ff_hex_to_data(iv, info.iv + 2);
			mgt->has_iv = 1;
		}else{
			mgt->has_iv = 0;
		}
		if(key_type ==KEY_AES_128){
			key_priv_info->key_type = key_type;
			if(mgt->has_iv>0){
				memcpy(key_priv_info->iv,iv,sizeof(key_priv_info->iv));
			}
			
			av_log(NULL,AV_LOG_INFO,"aes key location : %s\n",info.uri);
			av_strlcpy(key_priv_info->key_from, info.uri, sizeof(key_priv_info->key_from));
			key_priv_info->is_have_key_file = 0;
			mgt->key_tmp = key_priv_info;
			mgt->flags |= KEY_FLAG;
			return -(TRICK_LOGIC_BASE+0);
			
		}else{
			av_log(NULL,AV_LOG_INFO,"just only support aes key\n");
			av_free(key_priv_info);
			key_priv_info = NULL;
		}
		
		
	}
	else{

		if(mgt->is_variant>0){
			if (!new_variant(mgt, mgt->bandwidth, p, mgt->prefix)) {	
				free_variant_list(mgt);
			 	return -1;
			}
			mgt->is_variant = 0;
			mgt->bandwidth  = 0;	
			
			return -(TRICK_LOGIC_BASE+2);
			
		}
		
		return 0;
	}
	return enditem;
}
Exemplo n.º 5
0
static int parse_playlist(AppleHTTPContext *c, const char *url,
                          struct variant *var, ByteIOContext *in)
{
    int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
    char line[1024];
    const char *ptr;
    int close_in = 0;

    if (!in) {
        close_in = 1;
        if ((ret = url_fopen(&in, url, URL_RDONLY)) < 0)
            return ret;
    }

    read_chomp_line(in, line, sizeof(line));
    if (strcmp(line, "#EXTM3U")) {
        ret = AVERROR_INVALIDDATA;
        goto fail;
    }

    if (var)
        free_segment_list(var);
    c->finished = 0;
    while (!url_feof(in)) {
        read_chomp_line(in, line, sizeof(line));
        if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
            struct variant_info info = {{0}};
            is_variant = 1;
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
                               &info);
            bandwidth = atoi(info.bandwidth);
        } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
            c->target_duration = atoi(ptr);
        } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
            if (!var) {
                var = new_variant(c, 0, url, NULL);
                if (!var) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
            }
            var->start_seq_no = atoi(ptr);
        } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
            c->finished = 1;
        } else if (av_strstart(line, "#EXTINF:", &ptr)) {
            is_segment = 1;
            duration   = atoi(ptr);
        } else if (av_strstart(line, "#", NULL)) {
            continue;
        } else if (line[0]) {
            if (is_variant) {
                if (!new_variant(c, bandwidth, line, url)) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                is_variant = 0;
                bandwidth  = 0;
            }
            if (is_segment) {
                struct segment *seg;
                if (!var) {
                    var = new_variant(c, 0, url, NULL);
                    if (!var) {
                        ret = AVERROR(ENOMEM);
                        goto fail;
                    }
                }
                seg = av_malloc(sizeof(struct segment));
                if (!seg) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                seg->duration = duration;
                make_absolute_url(seg->url, sizeof(seg->url), url, line);
                dynarray_add(&var->segments, &var->n_segments, seg);
                is_segment = 0;
            }
        }
    }
    c->last_load_time = av_gettime();

fail:
    if (close_in)
        url_fclose(in);
    return ret;
}
Exemplo n.º 6
0
static int parse_playlist(HLSContext *c, const char *url,
                          struct variant *var, AVIOContext *in)
{
	char* resolution;
    int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
    double duration = 0.0;
    enum KeyType key_type = KEY_NONE;
    uint8_t iv[16] = "";
    int has_iv = 0;
    char key[MAX_URL_SIZE] = "";
    char line[1024];
    const char *ptr;
    int close_in = 0;

    if (!in) {
        close_in = 1;
        if ((ret = avio_open2(&in, url, AVIO_FLAG_READ,
                              c->interrupt_callback, NULL)) < 0)
            return ret;
    }

    read_chomp_line(in, line, sizeof(line));
    if (strcmp(line, "#EXTM3U")) {
        ret = AVERROR_INVALIDDATA;
        goto fail;
    }

    if (var) {
        free_segment_list(var);
        var->finished = 0;
    }
    while (!url_feof(in)) {
		static int a = 0;

        read_chomp_line(in, line, sizeof(line));
        if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
            struct variant_info info = {{0}};
            is_variant = 1;
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
                               &info);
            bandwidth = atoi(info.bandwidth);
            resolution = info.resolution;
			   for(uint32_t i=0; i<20; i++) {
				if(info.resolution[i] == 'x') {
					memcpy(info.width, info.resolution, i);
					memcpy(info.height, info.resolution+i+1, 20-i);
					c->ctx->width = atoi(info.width);
					c->ctx->height = atoi(info.height);
					break;
				}
			}
			LOGI("resolution = %s, width = %s, height = %s",info.resolution, info.width, info.height);
        } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {
            struct key_info info = {{0}};
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
                               &info);
            key_type = KEY_NONE;
            has_iv = 0;
            if (!strcmp(info.method, "AES-128"))
                key_type = KEY_AES_128;
            if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
                ff_hex_to_data(iv, info.iv + 2);
                has_iv = 1;
            }
            av_strlcpy(key, info.uri, sizeof(key));
        } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
            if (!var) {
                var = new_variant(c, 0, url, NULL);
                if (!var) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
            }
            var->target_duration = atof(ptr);
        } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
            if (!var) {
                var = new_variant(c, 0, url, NULL);
                if (!var) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
            }
            var->start_seq_no = atoi(ptr);
//            LOGV("EXT-X-MEDIA-SEQUENCE = %d", var->start_seq_no);
        } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
            if (var)
                var->finished = 1;
//            static int a = 0;
//            FILE *fp = fopen( "/mnt/sdcard/Die_Hls.txt", "wta+");
//            fprintf(fp, "Line = %d, Times = %d, recive EXT-X-ENDLIST", __LINE__, a);
//            fclose(fp);
//            a++;
        } else if (av_strstart(line, "#EXTINF:", &ptr)) {
            is_segment = 1;
            duration   = atof(ptr);
        } else if (av_strstart(line, "#", NULL)) {
            continue;
        } else if (line[0]) {
            if (is_variant) {
                if (!new_variant(c, bandwidth, line, url)) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                is_variant = 0;
                bandwidth  = 0;
            }
            if (is_segment) {
                struct segment *seg;
                if (!var) {
                    var = new_variant(c, 0, url, NULL);
                    if (!var) {
                        ret = AVERROR(ENOMEM);
                        goto fail;
                    }
                }
                seg = av_malloc(sizeof(struct segment));
                if (!seg) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                seg->duration = duration;
                seg->key_type = key_type;
                if (has_iv) {
                    memcpy(seg->iv, iv, sizeof(iv));
                } else {
                    int seq = var->start_seq_no + var->n_segments;
                    memset(seg->iv, 0, sizeof(seg->iv));
                    AV_WB32(seg->iv + 12, seq);
                }
                ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);
                ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);
                dynarray_add(&var->segments, &var->n_segments, seg);
                is_segment = 0;
            }
        }
    }
    if (var)
        var->last_load_time = av_gettime();

fail:
    if (close_in)
        avio_close(in);
    return ret;
}
Exemplo n.º 7
0
static int parse_playlist(HLSContext *c, const char *url,
                          struct variant *var, AVIOContext *in)
{
    int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
    enum KeyType key_type = KEY_NONE;
    uint8_t iv[16] = "";
    int has_iv = 0;
    char key[MAX_URL_SIZE] = "";
    char line[1024];
    const char *ptr;
    int close_in = 0;
    const char *locattion=NULL;
    int totaltime=0;
    int isdiscontinued=0;
	
    if (!in) {
        close_in = 1;
#ifdef  AVIO_OPEN2	
        if ((ret = avio_open2(&in, url, AVIO_FLAG_READ | URL_NO_LP_BUFFER,c->interrupt_callback, NULL)) < 0)
            return ret;
#else
	if ((ret = avio_open(&in, url, AVIO_FLAG_READ | URL_NO_LP_BUFFER)) < 0){
		av_log(NULL, AV_LOG_ERROR, "parse_playlist :open [%s]failed=%d\n",url,ret);	 
            return ret;
	}		
#endif
    }
    if(in->reallocation)
		locattion=in->reallocation;
    else
		locattion=url;
    read_chomp_line(in, line, sizeof(line));
    if (strcmp(line, "#EXTM3U")) {
	 av_log(NULL, AV_LOG_ERROR, "not a valid m3u file,first line is [%s]\n",line);	 
        ret = AVERROR_INVALIDDATA;
        goto fail;
    }

    if (var) {
        free_segment_list(var);
        var->finished = 0;
    }
    while (1) {
		int sret;
		 line[0]=0;
		 if(url_interrupt_cb())
		 	break;
	        sret=read_chomp_line(in, line, sizeof(line));
		 if(sret<0){
		 	 av_log(NULL, AV_LOG_ERROR, "read_chomp_line end,ret=%d,var=%x,c->n_variants=%x\n",sret,var,c->n_variants);	 
		 	ret=(var!=NULL ||c->n_variants>0)?0:sret;
		 	break;
		 }
	    av_log(NULL, AV_LOG_INFO+1, "parse_playlist :[%s]\n",line);	 
        if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
            struct variant_info info = {{0}};
            is_variant = 1;
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
                               &info);
            bandwidth = atoi(info.bandwidth);
        } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {
            struct key_info info = {{0}};
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
                               &info);
            key_type = KEY_NONE;
            has_iv = 0;
            if (!strcmp(info.method, "AES-128"))
                key_type = KEY_AES_128;
            if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
                ff_hex_to_data(iv, info.iv + 2);
                has_iv = 1;
            }
            av_strlcpy(key, info.uri, sizeof(key));
        } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
            if (!var) {
                var = new_variant(c, 0, url, NULL);
                if (!var) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
            }
            var->target_duration = atoi(ptr);
        } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
            if (!var) {
                var = new_variant(c, 0, url, NULL);
                if (!var) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
            }
            var->start_seq_no = atoi(ptr);
        } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
            if (var)
                var->finished = 1;
        } else if (av_strstart(line, "#EXTINF:", &ptr)) {
            is_segment = 1;
            duration   = atoi(ptr);
        }  else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
            isdiscontinued   = 1;
        } else if (av_strstart(line, "#", NULL)) {
            continue;
        } else if (line[0]) {
            if (is_variant) {
                if (!new_variant(c, bandwidth, line, locattion)) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                is_variant = 0;
                bandwidth  = 0;
            }
            if (is_segment) {
                struct segment *seg;
                if (!var) {
                    var = new_variant(c, 0, url, NULL);
                    if (!var) {
                        ret = AVERROR(ENOMEM);
                        goto fail;
                    }
                }
                seg = av_malloc(sizeof(struct segment));
                if (!seg) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                seg->duration = duration;
                seg->key_type = key_type;
		  seg->seg_starttime=totaltime;	
		  seg->flags=DISCONTINUE_FLAG;
		  totaltime+=duration;
                if (has_iv) {
                    memcpy(seg->iv, iv, sizeof(iv));
                } else {
                    int seq = var->start_seq_no + var->n_segments;
                    memset(seg->iv, 0, sizeof(seg->iv));
                    AV_WB32(seg->iv + 12, seq);
                }
                ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);
                ff_make_absolute_url(seg->url, sizeof(seg->url), locattion, line);
                dynarray_add(&var->segments, &var->n_segments, seg);
                is_segment = 0;
            }
        }
    }
    if (var){
        var->last_load_time = av_gettime();
	 var->total_time_s=totaltime;	
     }
fail:
    if (close_in)
        avio_close(in);
    return ret;
}
Exemplo n.º 8
0
static int parse_playlist(HLSContext *c, const char *url,
                          struct playlist *pls, AVIOContext *in)
{
    int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
    int64_t duration = 0;
    enum KeyType key_type = KEY_NONE;
    uint8_t iv[16] = "";
    int has_iv = 0;
    char key[MAX_URL_SIZE] = "";
    char line[MAX_URL_SIZE];
    const char *ptr;
    int close_in = 0;
    uint8_t *new_url = NULL;

    if (!in) {
        AVDictionary *opts = NULL;
        close_in = 1;
        /* Some HLS servers don't like being sent the range header */
        av_dict_set(&opts, "seekable", "0", 0);

        // broker prior HTTP options that should be consistent across requests
        av_dict_set(&opts, "user-agent", c->user_agent, 0);
        av_dict_set(&opts, "cookies", c->cookies, 0);
        av_dict_set(&opts, "headers", c->headers, 0);

        ret = avio_open2(&in, url, AVIO_FLAG_READ,
                         c->interrupt_callback, &opts);
        av_dict_free(&opts);
        if (ret < 0)
            return ret;
    }

    if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0)
        url = new_url;

    read_chomp_line(in, line, sizeof(line));
    if (strcmp(line, "#EXTM3U")) {
        ret = AVERROR_INVALIDDATA;
        goto fail;
    }

    if (pls) {
        free_segment_list(pls);
        pls->finished = 0;
    }
    while (!url_feof(in)) {
        read_chomp_line(in, line, sizeof(line));
        if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
            struct variant_info info = {{0}};
            is_variant = 1;
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
                               &info);
            bandwidth = atoi(info.bandwidth);
        } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {
            struct key_info info = {{0}};
            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
                               &info);
            key_type = KEY_NONE;
            has_iv = 0;
            if (!strcmp(info.method, "AES-128"))
                key_type = KEY_AES_128;
            if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
                ff_hex_to_data(iv, info.iv + 2);
                has_iv = 1;
            }
            av_strlcpy(key, info.uri, sizeof(key));
        } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
            if (!pls) {
                if (!new_variant(c, 0, url, NULL)) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                pls = c->playlists[c->n_playlists - 1];
            }
            pls->target_duration = atoi(ptr) * AV_TIME_BASE;
        } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
            if (!pls) {
                if (!new_variant(c, 0, url, NULL)) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                pls = c->playlists[c->n_playlists - 1];
            }
            pls->start_seq_no = atoi(ptr);
        } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
            if (pls)
                pls->finished = 1;
        } else if (av_strstart(line, "#EXTINF:", &ptr)) {
            is_segment = 1;
            duration   = atof(ptr) * AV_TIME_BASE;
        } else if (av_strstart(line, "#", NULL)) {
            continue;
        } else if (line[0]) {
            if (is_variant) {
                if (!new_variant(c, bandwidth, line, url)) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                is_variant = 0;
                bandwidth  = 0;
            }
            if (is_segment) {
                struct segment *seg;
                if (!pls) {
                    if (!new_variant(c, 0, url, NULL)) {
                        ret = AVERROR(ENOMEM);
                        goto fail;
                    }
                    pls = c->playlists[c->n_playlists - 1];
                }
                seg = av_malloc(sizeof(struct segment));
                if (!seg) {
                    ret = AVERROR(ENOMEM);
                    goto fail;
                }
                seg->duration = duration;
                seg->key_type = key_type;
                if (has_iv) {
                    memcpy(seg->iv, iv, sizeof(iv));
                } else {
                    int seq = pls->start_seq_no + pls->n_segments;
                    memset(seg->iv, 0, sizeof(seg->iv));
                    AV_WB32(seg->iv + 12, seq);
                }
                ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);
                ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);
                dynarray_add(&pls->segments, &pls->n_segments, seg);
                is_segment = 0;
            }
        }
    }
    if (pls)
        pls->last_load_time = av_gettime();

fail:
    av_free(new_url);
    if (close_in)
        avio_close(in);
    return ret;
}