ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

MPEG DASH编码的基于frame的视频数据集下载

2019-08-31 14:37:39  阅读:281  来源: 互联网

标签:视频 MPEG frame len DASH time bitrate GOP


文章目录

MPEG DASH简介

  1. MPEG DASH是三大流媒体协议之一:MPEG DASH, HLS,Smooth Streaming. MPEG DASH诞生的目的是为了统一标准,因此是兼容SmoothStreaming和HLS的. 同时支持TS profile和 ISO profile,支持节目观看等级控制,支持父母锁. 详细介绍请看三种主流的流媒体协议MEPG DASH,HLS,Smooth Streaming及其manifest 文件字段解释.
  2. Manifest.mpd (MPD:Media Presentation Description) 文件是MPEG DASH编码视频的索引文件,该文件包含了整个mpeg dash码流的构成(manifest以.mpd结尾). 其优势就是不需要流媒体服务器缓存该视频的全部视频流,客户端请求视频服务器,服务器将manifest.mpd发送给客户端,客户端可以根据视频的URL+不同的byte range指定(chunk的url)进行任意chunk的下载,更加灵活.详细请看MPEG DASH编码的基于chunk的视频数据集下载
  3. 但其缺点是:
  • 传输时延长.由于video provider到video streaming server之间的网络拓扑复杂,所以仅考虑video streaming server到client之间的可控时延.可以表示为:
    T(s,c)=Ttrcoder(s)+Ttrans(s,c)+Twaite(c)T(s,c)=T^{trcoder}(s)+T^{trans}(s,c)+T^{waite}(c)T(s,c)=Ttrcoder(s)+Ttrans(s,c)+Twaite(c)

    由于转码服务器需要进行2次转码,实现不同码率视频之间的segment对齐.增加了转码服务器的资源开销,也增加了转码服务器的转码时间.只有整个chunk完整下载到客户端,客户端才能进行视频播放,增加了客户端的等待时延.
  • 码率选择保守.由于网络吞吐量变化极大且难以预测,离当前时刻越远,预测越不精准,所以根据网络吞吐量的预测和当前buffer的大小进行预测下一个chunk的码率,为了避免卡顿,码率将会更加保守.并且随着chunk的大小增加,更加保守.
  • 码率切换将更加笨重.由于仅在chunk边界进行码率选择,所以chunk期间内的码率不一定是当前时刻的最优码率.
  1. 为了改进这些缺点,需要构建一套基于帧的视频传输框架,不仅解决chunk所可以解决的问题,而且可以更优的用户体验.

MPEG DASH编码的基于frame的视频数据集下载

构建基于帧的视频传输框架的前提是要有基于帧的原始视频数据集. 目前我们可以获取很多基于I帧对齐的原始视频数据集,这是因为现有的转码服务器会进行2轮转码,自动将不同码率的视频实现I帧对齐.但要去除 I帧对齐所带来的时延和资源开销,必须获取I帧不对齐的视频数据集.

数据集来源

本博文使用的原始视频数据集来源于竞赛

基于frame的数据集重构步骤

  1. I帧数据与非I帧数据的分离.
  2. I帧数据与非I帧数据的重构.关键在于:
  • 如何获取GOP的长度.第一个GOP的长度通过np.random.choice()获取,其他的GOP长度,通过真实的I帧不对齐数据集中GOP长度的概率分布,进行依概率获取.
  • 如何匹配I帧与非I帧. 通过遍历I帧数据,获取插入I帧位置的I帧与上下非I帧的帧到达时间差最小.
  • 如何实现I帧与非I帧的帧到达时间平滑.这是通过统计获取的. 在真实的基于frame的视频数据集中, I帧的到达时间间隔和其他帧的到达时间间隔相差在毫秒级. 进而可以认为所有帧的到达间隔与帧类型无关,仅仅与视频提供者到流媒体服务器的网络有关.所以我才用帧到达时间没有与原始数据帧的时间完全对应,而是自适应的进行时间浮动,实现时间的平滑.

实现代码

以下是根据I帧对齐的视频数据集,进行重构的代码,实现不同码率视频轨迹之间I帧不对齐,GOP不等长, 同一码率视频轨迹内部,GOP也不等长,依真实视频轨迹数据集中GOP长度的概率分布,随机获取.

# 原始数据集,不同码率视频轨迹之间I帧对齐,GOP等长=50.
# 原始数据集,同一码率视频轨迹内部GOP固定=50
# 构造数据集.不同码率视频轨迹之间I帧不对齐,GOP不等长,{500kb/s:25,850kb/s:25,1200kb/s:49,1850kb/s:49}
# 构造数据集.同一码率视频轨迹内部,GOP也不等长,依真实视频轨迹数据集中GOP长度的概率分布,随机获取.

# !/usr/bin/evn python3
# -*- coding:UTF-8 -*-

import numpy as np
import os

BASE_VIDEO_TRACE = '../frame_datasets/video_final/frame_trace_'
BITRATE_LEVELS = 2
bitrate_level = 4
bitrate_gop = {0: 0, 1: 0, 2: 1, 3: 1}

# 获取[500kb/s,1200kb/s]的真实视频数据集的GOP长度分布
def GOP_len_describe():
    frame_arrive_time = []
    frame_size = []
    frame_time_len = []
    gop_flag = []

    for bitrate in range(BITRATE_LEVELS):
            frame_arrive_time.append([])
            frame_size.append([])
            frame_time_len.append([])
            gop_flag.append([])
            with open(BASE_VIDEO_TRACE + str(bitrate)) as f:
                for line in f:
                    frame_arrive_time[bitrate].append(float(line.split()[0]))
                    frame_size[bitrate].append(float(line.split()[1]))
                    frame_time_len[bitrate].append(1.0/float(line.split()[3]))
                    gop_flag[bitrate].append(int(float(line.split()[2])))

    GOP_len = {}
    for bitrate in range(BITRATE_LEVELS):
        GOP_len[bitrate] = {}
        num = 0
        for i in range(len(gop_flag[bitrate])):
            num += 1
            if gop_flag[bitrate][i] == 1:
                if num in GOP_len[bitrate]:
                    GOP_len[bitrate][num] += 1
                else:
                    GOP_len[bitrate][num] = 1
                num = 0
    return GOP_len

# GOP长度的依概率选择. gop is in [0,1]. 用于表示服从哪一个分布.
# gop == 0:表示服从码率为500kb/s的GOP分布,GOP长度的众数为25
# gop == 1:表示服从码率为1200kb/s的GOP分布,GOP长度的众数为49
def GOP_len_choise(gop):
    GOP_len = GOP_len_describe()
    gop_len = GOP_len[gop]
    gop_len_value = [i for i in gop_len.values()]
    gop_len_key = [i for i in gop_len.keys()]
    probs = [i/np.sum([gop_len_value]) for i in gop_len_value]
    choise = np.random.choice(gop_len_key, p=probs)
    return choise

# 选择离当前P帧在时间上最近的I帧.
def choise_near_frame(time_list, time):
    id = 0
    for i in range(len(time_list)):
        if np.abs(time_list[i] - time) < np.abs(time_list[id] - time):
            id = i
    return id

# 视频数据集重构,I帧对齐的视频数据集,重构为I帧不对齐的视频数据集
# 其中帧到达时间没有与原始数据帧的时间完全对应,这是因为I帧的到达时间间隔和其他帧的到达时间间隔相差在毫秒级
# 进而可以认为所有帧的到达间隔与帧类型无关,仅仅与视频提供者到流媒体服务器的网络有关.
def video_gen(video_traces, video_traces_new):
    # 帧到达时间
    frame_arrive_time = []
    # I帧到达时间
    key_frame_arrive_time = []
    key_frame_size = []
    # 非I帧到达时间
    other_frame_arrive_time = []
    other_frame_size = []

    for bitrate in range(bitrate_level):
            frame_arrive_time.append([])
            key_frame_arrive_time.append([])
            key_frame_size.append([])
            other_frame_arrive_time.append([])
            other_frame_size.append([])

            # I帧与非I帧的信息读取
            with open(video_traces + str(bitrate), 'r') as f:
                for line in f:
                    frame_arrive_time[bitrate].append(float(line.split()[0]))
                    if int(line.split()[2]) == 1:
                        key_frame_arrive_time[bitrate].append(float(line.split()[0]))
                        key_frame_size[bitrate].append(float(line.split()[1]))
                    else:
                        other_frame_arrive_time[bitrate].append(float(line.split()[0]))
                        other_frame_size[bitrate].append(float(line.split()[1]))

            # 视频数据重构
            with open(video_traces_new + str(bitrate), 'w') as f1:
                n = 0   # 表示非I帧的序列号
                m = 0   # 表示帧的序列号
                choise = np.random.choice(25)   # 选择GOP的长度
                while 1:
                    # 在GOP边界,插入I帧
                    if choise == 1:
                        id = choise_near_frame(key_frame_arrive_time[bitrate], other_frame_arrive_time[bitrate][n])
                        f1.write(str(frame_arrive_time[bitrate][m]) + ' ' + \
                                 str(key_frame_size[bitrate][id]) + ' ' + \
                                 str(25) + ' ' + \
                                 str(1) + '\n')
                        choise = GOP_len_choise(bitrate_gop[bitrate])
                        m += 1
                    # 其他情况,插入非I帧
                    else:
                        f1.write(str(frame_arrive_time[bitrate][m]) + ' ' + \
                                 str(other_frame_size[bitrate][n]) + ' ' + \
                                 str(25) + ' ' + \
                                 str(0) + '\n')
                        choise -= 1
                        n += 1
                        m += 1
                    if m >= len(frame_arrive_time[bitrate])-1:
                        break

def main():
    video_type = ["room", "game", "sports"]
    for i in range(len(video_type)):
        video_traces = "../frame_datasets/" + video_type[i] + "/frame_trace_"
        video_traces_new = "./" + video_type[i] + "/frame_trace_"
        if not os.path.exists(video_type[i]):
            os.makedirs(video_type[i])
        video_gen(video_traces, video_traces_new)


main()

如有任何问题,欢迎留言.

标签:视频,MPEG,frame,len,DASH,time,bitrate,GOP
来源: https://blog.csdn.net/qq_31813549/article/details/100166858

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有