def collect_ssim(video_acked_results, postgres_cursor):
    # process InfluxDB data
    x = {}
    for pt in video_acked_results['video_acked']:
        expt_id = int(pt['expt_id'])
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        # index x by (abr, cc)
        abr_cc = (expt_config['abr'], expt_config['cc'])
        if abr_cc not in x:
            x[abr_cc] = []

        if pt['ssim_index'] is not None:
            ssim_index = float(pt['ssim_index'])
            x[abr_cc].append(ssim_index)

    # calculate average SSIM in dB and record number of chunks
    ssim = {}
    num_chunks = {}
    for abr_cc in x:
        num_chunks[abr_cc] = len(x[abr_cc])
        avg_ssim_index = np.mean(x[abr_cc])
        avg_ssim_db = ssim_index_to_db(avg_ssim_index)
        ssim[abr_cc] = avg_ssim_db

    return ssim, num_chunks
    def process_expired(self):
        # read and process expired values
        expired_sessions = self.expiry_list.expired

        for session in expired_sessions:
            s = self.smap[session]

            if not self.valid_expired_session(session):
                del self.smap[session]
                continue

            expt_id = str(session[-1])
            expt_config = retrieve_expt_config(expt_id, self.expt,
                                               self.postgres_cursor)

            abr_cc = get_abr_cc(expt_config)
            if abr_cc not in self.out:
                self.out[abr_cc] = {}
                self.out[abr_cc]['total_play'] = 0
                self.out[abr_cc]['total_rebuf'] = 0

            session_play = ((s['max_play_time'] - s['min_play_time']) /
                            np.timedelta64(1, 's'))
            session_rebuf = s['max_cum_rebuf'] - s['min_cum_rebuf']

            self.out[abr_cc]['total_play'] += session_play
            self.out[abr_cc]['total_rebuf'] += session_rebuf

            del self.smap[session]

        # clean processed expired values
        self.expiry_list.expired = []
def collect_rebuffer(client_buffer_results, postgres_cursor):
    # process InfluxDB data
    x = {}
    for pt in client_buffer_results['client_buffer']:
        expt_id = int(pt['expt_id'])
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        # index x by (abr, cc)
        abr_cc = (expt_config['abr'], expt_config['cc'])
        if abr_cc not in x:
            x[abr_cc] = {}

        session = (pt['user'], int(pt['init_id']), pt['channel'],
                   int(pt['expt_id']))
        if session not in x[abr_cc]:
            x[abr_cc][session] = {}
            x[abr_cc][session]['min_time'] = None
            x[abr_cc][session]['max_time'] = None
            x[abr_cc][session]['min_cum_rebuf'] = None
            x[abr_cc][session]['max_cum_rebuf'] = None

        # shorthand variable
        y = x[abr_cc][session]
        ts = try_parsing_time(pt['time'])
        cum_rebuf = float(pt['cum_rebuf'])

        if y['min_time'] is None or ts < y['min_time']:
            y['min_time'] = ts
        if y['max_time'] is None or ts > y['max_time']:
            y['max_time'] = ts

        if y['min_cum_rebuf'] is None or cum_rebuf < y['min_cum_rebuf']:
            y['min_cum_rebuf'] = cum_rebuf
        if y['max_cum_rebuf'] is None or cum_rebuf > y['max_cum_rebuf']:
            y['max_cum_rebuf'] = cum_rebuf

    # calculate rebuffer rate
    rebuffer = {}
    for abr_cc in x:
        total_play = 0
        total_rebuf = 0

        for session in x[abr_cc]:
            # shorthand variable
            y = x[abr_cc][session]
            total_play += (y['max_time'] - y['min_time']).total_seconds()
            total_rebuf += y['max_cum_rebuf'] - y['min_cum_rebuf']

        if total_play == 0:
            sys.exit('Error: total play time is 0')

        rebuf_rate = total_rebuf / total_play
        rebuffer[abr_cc] = rebuf_rate * 100

    return rebuffer
Exemplo n.º 4
0
def process_rebuffer_session(session, s):
    # exclude too short sessions
    if s['play_time'] < 5:
        return

    expt_id = str(session[-1])
    expt_config = retrieve_expt_config(expt_id, expt, postgres_cursor)
    abr_cc = get_abr_cc(expt_config)

    global g_rebuffer
    if abr_cc not in g_rebuffer:
        g_rebuffer[abr_cc] = {}
        g_rebuffer[abr_cc]['total_play'] = 0
        g_rebuffer[abr_cc]['total_rebuf'] = 0

    g_rebuffer[abr_cc]['total_play'] += s['play_time']
    g_rebuffer[abr_cc]['total_rebuf'] += s['cum_rebuf']
Exemplo n.º 5
0
def calculate_rebuffer_by_abr_cc(d, expt_id_cache, postgres_cursor):
    x = {}  # indexed by (abr, cc)

    for session in d:
        expt_id = int(session[-1])
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        abr_cc = get_abr_cc(expt_config)
        if abr_cc not in x:
            x[abr_cc] = {}
            x[abr_cc]['total_play'] = 0
            x[abr_cc]['total_rebuf'] = 0

        x[abr_cc]['total_play'] += d[session]['play']
        x[abr_cc]['total_rebuf'] += d[session]['rebuf']

    return x
Exemplo n.º 6
0
def do_collect_ssim(s_str, e_str, d):
    sys.stderr.write('Processing video_acked data between {} and {}\n'
                     .format(s_str, e_str))
    video_acked_results = query_measurement(
        influx_client, 'video_acked', s_str, e_str)['video_acked']

    for pt in video_acked_results:
        expt_id = str(pt['expt_id'])
        expt_config = retrieve_expt_config(expt_id, expt, postgres_cursor)
        abr_cc = get_abr_cc(expt_config)

        if abr_cc not in d:
            d[abr_cc] = [0.0, 0]  # sum, count

        ssim_index = get_ssim_index(pt)
        if ssim_index is not None and ssim_index != 1:
            d[abr_cc][0] += ssim_index
            d[abr_cc][1] += 1
Exemplo n.º 7
0
def do_collect_ssim(video_acked_results, expt_id_cache, postgres_cursor):
    # process InfluxDB data
    x = {}
    for pt in video_acked_results['video_acked']:
        expt_id = get_expt_id(pt)
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)

        abr_cc = get_abr_cc(expt_config)
        if abr_cc not in x:
            x[abr_cc] = []

        ssim_index = get_ssim_index(pt)
        if ssim_index is not None:
            x[abr_cc].append(ssim_index)

    # calculate average SSIM in dB
    for abr_cc in x:
        avg_ssim_index = np.mean(x[abr_cc])
        avg_ssim_db = ssim_index_to_db(avg_ssim_index)
        x[abr_cc] = avg_ssim_db

    return x
Exemplo n.º 8
0
def collect_ssim(video_acked_results, postgres_cursor):
    # process InfluxDB data
    x = {}
    for pt in video_acked_results['video_acked']:
        expt_id = int(pt['expt_id'])
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        # index x by (abr, cc)
        abr_cc = (expt_config['abr'], expt_config['cc'])
        if abr_cc not in x:
            x[abr_cc] = []

        ssim_index = get_ssim_index(pt)
        if ssim_index is not None:
            x[abr_cc].append(ssim_index)

    # calculate average SSIM in dB
    ssim = {}
    for abr_cc in x:
        avg_ssim_index = np.mean(x[abr_cc])
        avg_ssim_db = ssim_index_to_db(avg_ssim_index)
        ssim[abr_cc] = avg_ssim_db

    return ssim
Exemplo n.º 9
0
def calculate_trans_times(video_sent_results, video_acked_results, cc,
                          postgres_cursor):
    d = {}
    last_video_ts = {}

    for pt in video_sent_results['video_sent']:
        expt_id = int(pt['expt_id'])
        session = (pt['user'], int(pt['init_id']), pt['channel'], expt_id)

        # filter data points by congestion control
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        if cc is not None and expt_config['cc'] != cc:
            continue

        if session not in d:
            d[session] = {}
            last_video_ts[session] = None

        video_ts = int(pt['video_ts'])

        if last_video_ts[session] is not None:
            if video_ts != last_video_ts[session] + VIDEO_DURATION:
                sys.stderr.write('Warning in session {}: video_ts={}\n'.format(
                    session, video_ts))
                continue

        last_video_ts[session] = video_ts

        d[session][video_ts] = {}
        dsv = d[session][video_ts]  # short name

        dsv['sent_ts'] = try_parsing_time(pt['time'])
        dsv['size'] = float(pt['size']) / PKT_BYTES  # bytes -> packets
        # byte/second -> packet/second
        dsv['delivery_rate'] = float(pt['delivery_rate']) / PKT_BYTES
        dsv['cwnd'] = float(pt['cwnd'])
        dsv['in_flight'] = float(pt['in_flight'])
        dsv['min_rtt'] = float(pt['min_rtt']) / MILLION  # us -> s
        dsv['rtt'] = float(pt['rtt']) / MILLION  # us -> s
        # dsv['ssim_index'] = get_ssim_index(pt)

    for pt in video_acked_results['video_acked']:
        expt_id = int(pt['expt_id'])
        session = (pt['user'], int(pt['init_id']), pt['channel'], expt_id)

        # filter data points by congestion control
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        if cc is not None and expt_config['cc'] != cc:
            continue

        if session not in d:
            sys.stderr.write('Warning: ignored session {}\n'.format(session))
            continue

        video_ts = int(pt['video_ts'])
        if video_ts not in d[session]:
            sys.stderr.write('Warning: ignored acked video_ts {} in the '
                             'session {}\n'.format(video_ts, session))
            continue

        dsv = d[session][video_ts]  # short name

        # calculate transmission time
        sent_ts = dsv['sent_ts']
        acked_ts = try_parsing_time(pt['time'])
        dsv['acked_ts'] = acked_ts
        dsv['trans_time'] = (acked_ts - sent_ts).total_seconds()

    return d
Exemplo n.º 10
0
def collect_rebuffer(client_buffer_results, postgres_cursor):
    # process InfluxDB data
    last_ts = {}
    last_cum_rebuf = {}
    outlier_time = {}
    excluded_sessions = {}
    x = {}

    for pt in client_buffer_results['client_buffer']:
        expt_id = int(pt['expt_id'])
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        # index x by (abr, cc)
        abr_cc = (expt_config['abr'], expt_config['cc'])
        if abr_cc not in x:
            x[abr_cc] = {}

        # index x[abr_cc] by session
        session = (pt['user'], int(pt['init_id']), pt['channel'],
                   int(pt['expt_id']))

        if session not in last_ts:
            last_ts[session] = None
        if session not in last_cum_rebuf:
            last_cum_rebuf[session] = None
        if session not in outlier_time:
            outlier_time[session] = None

        if session not in x[abr_cc]:
            if session in excluded_sessions:
                # ignore sessions that were intentionally removed from x[abr_cc]
                continue

            x[abr_cc][session] = {}
            x[abr_cc][session]['min_play_time'] = None
            x[abr_cc][session]['max_play_time'] = None
            x[abr_cc][session]['min_cum_rebuf'] = None
            x[abr_cc][session]['max_cum_rebuf'] = None

        y = x[abr_cc][session]  # short name

        ts = try_parsing_time(pt['time'])
        buf = float(pt['buffer'])
        cum_rebuf = float(pt['cum_rebuf'])

        # verify that time is basically continuous in the same session
        if last_ts[session] is not None:
            diff = (ts - last_ts[session]).total_seconds()
            if diff > 60:  # a new but different session should be ignored
                continue
        last_ts[session] = ts

        # identify outliers: exclude the session if there is one-minute long
        # duration when buffer is lower than 1 second
        if buf > 1:
            outlier_time[session] = None
        else:
            if outlier_time[session] is None:
                outlier_time[session] = ts
            else:
                diff = (ts - outlier_time[session]).total_seconds()
                if diff > 30:
                    print('Outlier session', abr_cc, session)
                    del x[abr_cc][session]
                    excluded_sessions[session] = True
                    continue

        # identify stalls caused by slow video decoding
        if last_cum_rebuf[session] is not None:
            if buf > 5 and cum_rebuf > last_cum_rebuf[session] + 0.25:
                # should not have stalls
                print('Decoding stalls', abr_cc, session)
                del x[abr_cc][session]
                excluded_sessions[session] = True
                continue

        last_cum_rebuf[session] = cum_rebuf

        if pt['event'] == 'startup':
            y['min_play_time'] = ts
            y['min_cum_rebuf'] = cum_rebuf

        if y['max_play_time'] is None or ts > y['max_play_time']:
            y['max_play_time'] = ts

        if y['max_cum_rebuf'] is None or cum_rebuf > y['max_cum_rebuf']:
            y['max_cum_rebuf'] = cum_rebuf

    # calculate rebuffer rate
    rebuffer = {}
    total_play = {}
    total_rebuf = {}

    for abr_cc in x:
        abr_cc_play = 0
        abr_cc_rebuf = 0

        for session in x[abr_cc]:
            y = x[abr_cc][session]  # short name

            if y['min_play_time'] is None or y['min_cum_rebuf'] is None:
                continue

            sess_play = (y['max_play_time'] -
                         y['min_play_time']).total_seconds()
            sess_rebuf = y['max_cum_rebuf'] - y['min_cum_rebuf']

            # exclude short sessions
            if sess_play < 5:
                continue

            abr_cc_play += sess_play
            abr_cc_rebuf += sess_rebuf

        if abr_cc_play == 0:
            sys.exit('Error: {}: total play time is 0'.format(abr_cc))

        total_play[abr_cc] = abr_cc_play
        total_rebuf[abr_cc] = abr_cc_rebuf

        rebuf_rate = abr_cc_rebuf / abr_cc_play
        rebuffer[abr_cc] = rebuf_rate * 100

    return rebuffer, total_play, total_rebuf
Exemplo n.º 11
0
def calculate_trans_times(video_sent_results, video_acked_results,
                          cc, postgres_cursor):
    d = {}
    last_video_ts = {}

    for pt in video_sent_results['video_sent']:
        expt_id = get_expt_id(pt)
        session = (get_user(pt), int(pt['init_id']),
                   pt['channel'], expt_id)

        # filter data points by congestion control
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        if cc is not None and expt_config['cc'] != cc:
            continue

        if session not in d:
            d[session] = {}
            last_video_ts[session] = None

        video_ts = int(pt['video_ts'])

        if last_video_ts[session] is not None:
            if video_ts != last_video_ts[session] + VIDEO_DURATION:
                continue

        last_video_ts[session] = video_ts

        d[session][video_ts] = {}
        dsv = d[session][video_ts]  # short name

        dsv['sent_ts'] = np.datetime64(pt['time'])
        dsv['size'] = float(pt['size']) / PKT_BYTES  # bytes -> packets
        # byte/second -> packet/second
        dsv['delivery_rate'] = float(pt['delivery_rate']) / PKT_BYTES
        dsv['cwnd'] = float(pt['cwnd'])
        dsv['in_flight'] = float(pt['in_flight'])
        dsv['min_rtt'] = float(pt['min_rtt']) / MILLION  # us -> s
        dsv['rtt'] = float(pt['rtt']) / MILLION  # us -> s

    for pt in video_acked_results['video_acked']:
        expt_id = get_expt_id(pt)
        session = (get_user(pt), int(pt['init_id']),
                   pt['channel'], expt_id)

        # filter data points by congestion control
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        if cc is not None and expt_config['cc'] != cc:
            continue

        if session not in d:
            continue

        video_ts = int(pt['video_ts'])
        if video_ts not in d[session]:
            continue

        dsv = d[session][video_ts]  # short name

        # calculate transmission time
        sent_ts = dsv['sent_ts']
        acked_ts = np.datetime64(pt['time'])
        dsv['acked_ts'] = acked_ts
        dsv['trans_time'] = (acked_ts - sent_ts) / np.timedelta64(1, 's')

    return d
Exemplo n.º 12
0
def collect_rebuffer(client_buffer_results, postgres_cursor):
    # process InfluxDB data
    x = {}
    for pt in client_buffer_results['client_buffer']:
        expt_id = int(pt['expt_id'])
        expt_config = retrieve_expt_config(expt_id, expt_id_cache,
                                           postgres_cursor)
        # index x by (abr, cc)
        abr_cc = (expt_config['abr'], expt_config['cc'])
        if abr_cc not in x:
            x[abr_cc] = {}

        # index x[abr_cc] by session
        session = (pt['user'], int(pt['init_id']), pt['channel'],
                   int(pt['expt_id']))
        if session not in x[abr_cc]:
            x[abr_cc][session] = {}
            x[abr_cc][session]['min_play_time'] = None
            x[abr_cc][session]['max_play_time'] = None
            x[abr_cc][session]['min_cum_rebuf'] = None
            x[abr_cc][session]['max_cum_rebuf'] = None

        y = x[abr_cc][session]  # short name

        ts = try_parsing_time(pt['time'])
        cum_rebuf = float(pt['cum_rebuf'])

        if pt['event'] == 'startup':
            y['min_play_time'] = ts
            y['min_cum_rebuf'] = cum_rebuf

        if y['max_play_time'] is None or ts > y['max_play_time']:
            y['max_play_time'] = ts

        if y['max_cum_rebuf'] is None or cum_rebuf > y['max_cum_rebuf']:
            y['max_cum_rebuf'] = cum_rebuf

    # calculate rebuffer rate
    rebuffer = {}
    total_play = {}
    total_rebuf = {}

    for abr_cc in x:
        abr_cc_play = 0
        abr_cc_rebuf = 0

        for session in x[abr_cc]:
            y = x[abr_cc][session]  # short name

            if y['min_play_time'] is None or y['min_cum_rebuf'] is None:
                continue

            sess_play = (y['max_play_time'] -
                         y['min_play_time']).total_seconds()
            sess_rebuf = y['max_cum_rebuf'] - y['min_cum_rebuf']

            # exclude too short sessions
            if sess_play < 2:
                continue

            # TODO: identify and ignore outliers
            if sess_rebuf / sess_play > 0.5:
                continue

            abr_cc_play += sess_play
            abr_cc_rebuf += sess_rebuf

        if abr_cc_play == 0:
            sys.exit('Error: {}: total play time is 0'.format(abr_cc))

        total_play[abr_cc] = abr_cc_play
        total_rebuf[abr_cc] = abr_cc_rebuf

        rebuf_rate = abr_cc_rebuf / abr_cc_play
        rebuffer[abr_cc] = rebuf_rate * 100

    return rebuffer, total_play, total_rebuf