Example #1
0
def getDecrypter(key, iv):
    global USEDec
    if USEDec == 1:
        enc = AES.new(key, AES.MODE_CBC, iv)
    elif USEDec == 3:
        ivb = array.array('B', iv)
        keyb = array.array('B', key)
        enc = python_aes.new(keyb, 2, ivb)
    else:
        enc = androidsslPy._load_crypto_libcrypto()
        enc = enc(key, iv)
    return enc
Example #2
0
def getDecrypter(key,iv):
    global USEDec
    if USEDec==1:
        enc =AES.new(key, AES.MODE_CBC, iv)
    elif USEDec==3:
        ivb=array.array('B',iv)
        keyb= array.array('B',key)
        enc=python_aes.new(keyb, 2, ivb)
    else:
        enc =androidsslPy._load_crypto_libcrypto()
        enc = enc(key, iv)
    return  enc       
Example #3
0
def handle_basic_m3u(url):
    global iv
    global key
    global USEDec
    seq = 1
    enc = None
    nextlen = 5
    duration = 5
    targetduration=5
    for line in gen_m3u(url):
        if line.startswith('#EXT'):
            tag, attribs = parse_m3u_tag(line)
            if tag == '#EXTINF':
                duration = float(attribs[0])
            elif tag == '#EXT-X-TARGETDURATION':
                assert len(attribs) == 1, "too many attribs in EXT-X-TARGETDURATION"
                targetduration = int(attribs[0])
                pass
            elif tag == '#EXT-X-MEDIA-SEQUENCE':
                assert len(attribs) == 1, "too many attribs in EXT-X-MEDIA-SEQUENCE"
                seq = int(attribs[0])
            elif tag == '#EXT-X-KEY':
                attribs = parse_kv(attribs, ('METHOD', 'URI', 'IV'))
                assert 'METHOD' in attribs, 'expected METHOD in EXT-X-KEY'
                if attribs['METHOD'] == 'NONE':
                    assert 'URI' not in attribs, 'EXT-X-KEY: METHOD=NONE, but URI found'
                    assert 'IV' not in attribs, 'EXT-X-KEY: METHOD=NONE, but IV found'
                    enc = None
                elif attribs['METHOD'] == 'AES-128':
                    assert 'URI' in attribs, 'EXT-X-KEY: METHOD=AES-128, but no URI found'
                    #from Crypto.Cipher import AES
                    key = download_file(attribs['URI'].strip('"'))
                    assert len(key) == 16, 'EXT-X-KEY: downloaded key file has bad length'
                    if 'IV' in attribs:
                        assert attribs['IV'].lower().startswith('0x'), 'EXT-X-KEY: IV attribute has bad format'
                        iv = attribs['IV'][2:].zfill(32).decode('hex')
                        assert len(iv) == 16, 'EXT-X-KEY: IV attribute has bad length'
                    else:
                        iv = '\0'*8 + struct.pack('>Q', seq)
                    
                    if not USEDec==3:
                        enc = AES.new(key, AES.MODE_CBC, iv)
                    else:
                        ivb=array.array('B',iv)
                        keyb= array.array('B',key)
                        enc=python_aes.new(keyb, 2, ivb)
                    #enc = AES_CBC(key)
                    #print key
                    #print iv
                    #enc=AESDecrypter.new(key, 2, iv)
                else:
                    assert False, 'EXT-X-KEY: METHOD=%s unknown'%attribs['METHOD']
            elif tag == '#EXT-X-PROGRAM-DATE-TIME':
                assert len(attribs) == 1, "too many attribs in EXT-X-PROGRAM-DATE-TIME"
                # TODO parse attribs[0] as ISO8601 date/time
                pass
            elif tag == '#EXT-X-ALLOW-CACHE':
                # XXX deliberately ignore
                pass
            elif tag == '#EXT-X-ENDLIST':
                assert not attribs
                yield None
                return
            elif tag == '#EXT-X-STREAM-INF':
                raise ValueError("don't know how to handle EXT-X-STREAM-INF in basic playlist")
            elif tag == '#EXT-X-DISCONTINUITY':
                assert not attribs
                print "[warn] discontinuity in stream"
            elif tag == '#EXT-X-VERSION':
                assert len(attribs) == 1
                if int(attribs[0]) > SUPPORTED_VERSION:
                    print "[warn] file version %s exceeds supported version %d; some things might be broken"%(attribs[0], SUPPORTED_VERSION)
            #else:
            #    raise ValueError("tag %s not known"%tag)
        else:
            yield (seq, enc, duration, targetduration, line)
            seq += 1
def downloadInternal(url, file, maxbitrate=0, stopEvent=None, testing=False):
    global key
    global iv
    global USEDec
    global callbackDRM
    if stopEvent and stopEvent.isSet():
        return
    dumpfile = None
    #dumpfile=open('c:\\temp\\myfile.mp4',"wb")
    variants = []
    variant = None
    #url check if requires redirect
    redirurl = url
    try:
        print 'going gor  ', url
        res = getUrl(url, returnres=True)
        print 'here ', res
        if res.history:
            print 'history'
            redirurl = res.url
        res.close()
        if testing: return True
    except:
        traceback.print_exc()
    print 'redirurl', redirurl

    for line in gen_m3u(url):
        if line.startswith('#EXT'):
            tag, attribs = parse_m3u_tag(line)
            if tag == '#EXT-X-STREAM-INF':
                variant = attribs
        elif variant:
            variants.append((line, variant))
            variant = None
    print 'variants', variants
    if len(variants) == 0: url = redirurl
    if len(variants) == 1:
        url = urlparse.urljoin(redirurl, variants[0][0])
    elif len(variants) >= 2:
        print "More than one variant of the stream was provided."

        choice = -1
        lastbitrate = 0
        print 'maxbitrate', maxbitrate
        for i, (vurl, vattrs) in enumerate(variants):
            print i, vurl,
            for attr in vattrs:
                key, value = attr.split('=')
                key = key.strip()
                value = value.strip().strip('"')
                if key == 'BANDWIDTH':
                    print 'bitrate %.2f kbps' % (int(value) / 1024.0)
                    if int(value) <= int(maxbitrate) and int(
                            value) > lastbitrate:
                        choice = i
                        lastbitrate = int(value)
                elif key == 'PROGRAM-ID':
                    print 'program %s' % value,
                elif key == 'CODECS':
                    print 'codec %s' % value,
                elif key == 'RESOLUTION':
                    print 'resolution %s' % value,
                else:
                    print "unknown STREAM-INF attribute %s" % key
                    #raise ValueError("unknown STREAM-INF attribute %s"%key)
            print
        if choice == -1: choice = 0
        #choice = int(raw_input("Selection? "))
        print 'choose %d' % choice
        url = urlparse.urljoin(redirurl, variants[choice][0])

    #queue = Queue.Queue(1024) # 1024 blocks of 4K each ~ 4MB buffer
    control = ['go']
    #thread = threading.Thread(target=player_pipe, args=(queue, control,file))
    #thread.start()
    last_seq = -1
    targetduration = 5
    changed = 0
    glsession = None
    #if ':7777' in url:
    #    try:
    #        glsession=re.compile(':7777\/.*?m3u8.*?session=(.*?)&').findall(url)[0]
    #    except:
    #        pass

    try:
        while 1 == 1:  #thread.isAlive():
            if stopEvent and stopEvent.isSet():
                return
            medialist = list(handle_basic_m3u(url))

            if testing:
                if len(medialist) == 0: raise Exception('empty m3u8')
                return True
            playedSomething = False
            if medialist == None: return False

            if None in medialist:
                # choose to start playback at the start, since this is a VOD stream
                pass
            else:
                # choose to start playback three files from the end, since this is a live stream
                medialist = medialist[0:]
            #print 'medialist',medialist
            addsomewait = False
            lastKeyUrl = ""
            lastkey = None
            for media in medialist:

                if stopEvent and stopEvent.isSet():
                    return
                if media is None:
                    #queue.put(None, block=True)
                    return
                seq, encobj, duration, targetduration, media_url, vod = media
                addsomewait = True
                if seq > last_seq:
                    #print 'downloading.............',url

                    enc = None
                    if encobj:

                        codeurl, iv = encobj
                        if codeurl <> lastKeyUrl:
                            if codeurl.startswith('http'):
                                key = download_file(codeurl)
                            elif codeurl.startswith('LSDRMCallBack$'):
                                key = callbackDRM.DRMCallback(
                                    codeurl.split('LSDRMCallBack$')[1], url)
                            else:
                                key = codeurl
                            codeurl = lastKeyUrl
                        else:
                            key = lastkey
                        lastkey = key
                        if not USEDec == 3:
                            enc = AES.new(key, AES.MODE_CBC, iv)
                        else:
                            ivb = array.array('B', iv)
                            keyb = array.array('B', key)
                            enc = python_aes.new(keyb, 2, ivb)
                        #enc=AESDecrypter.new(key, 2, iv)

                    if glsession:
                        media_url = media_url.replace(
                            glsession, glsession[:-10] + ''.join(
                                random.choice(string.ascii_uppercase +
                                              string.digits)
                                for _ in range(10)))
                    try:
                        for chunk in download_chunks(urlparse.urljoin(
                                url, media_url),
                                                     enc=encobj):
                            if stopEvent and stopEvent.isSet():
                                return
                            #print '1. chunk available %d'%len(chunk)
                            if enc:
                                if not USEDec == 3:
                                    chunk = enc.decrypt(chunk)
                                else:
                                    chunkb = array.array('B', chunk)
                                    chunk = enc.decrypt(chunkb)
                                    chunk = "".join(map(chr, chunk))
                            #if enc: chunk = enc.decrypt(chunk,key,'CBC')
                            #print '2. chunk done %d'%len(chunk)
                            if dumpfile: dumpfile.write(chunk)
                            #queue.put(chunk, block=True)
                            send_back(chunk, file)
                            #print '3. chunk available %d'%len(chunk)
                        last_seq = seq
                        changed = 1
                        playedSomething = True
                    except:
                        pass
            '''if changed == 1:
                # initial minimum reload delay
                time.sleep(duration)
            elif changed == 0:
                # first attempt
                time.sleep(targetduration*0.5)
            elif changed == -1:
                # second attempt
                time.sleep(targetduration*1.5)
            else:
                # third attempt and beyond
                time.sleep(targetduration*3.0)
            
            changed -= 1
            '''
            return
            if not playedSomething:
                xbmc.sleep(2000 + (3000 if addsomewait else 0))
    except:
        control[0] = 'stop'
        raise
def downloadInternal(url,file,maxbitrate=0,stopEvent=None):
    global key
    global iv
    global USEDec
    if stopEvent and stopEvent.isSet():
        return
    dumpfile = None
    #dumpfile=open('c:\\temp\\myfile.mp4',"wb")
    variants = []
    variant = None
     #url check if requires redirect
    redirurl=url
    try:
        print 'going gor  ',url
        res=getUrl(url,returnres=True )
        print 'here ', res
        if res.history: 
            print 'history'
            redirurl=res.url
        res.close()
        
    except: traceback.print_exc()
    print 'redirurl',redirurl
    
    
    for line in gen_m3u(url):
        if line.startswith('#EXT'):
            tag, attribs = parse_m3u_tag(line)
            if tag == '#EXT-X-STREAM-INF':
                variant = attribs
        elif variant:
            variants.append((line, variant))
            variant = None
    print 'variants',variants
    if len(variants)==0: url=redirurl
    if len(variants) == 1:
        url = urlparse.urljoin(redirurl, variants[0][0])
    elif len(variants) >= 2:
        print "More than one variant of the stream was provided."

        choice=-1
        lastbitrate=0
        print 'maxbitrate',maxbitrate
        for i, (vurl, vattrs) in enumerate(variants):
            print i, vurl,
            for attr in vattrs:
                key, value = attr.split('=')
                key = key.strip()
                value = value.strip().strip('"')
                if key == 'BANDWIDTH':
                    print 'bitrate %.2f kbps'%(int(value)/1024.0)
                    if int(value)<=int(maxbitrate) and int(value)>lastbitrate:
                        choice=i
                        lastbitrate=int(value)
                elif key == 'PROGRAM-ID':
                    print 'program %s'%value,
                elif key == 'CODECS':
                    print 'codec %s'%value,
                elif key == 'RESOLUTION':
                    print 'resolution %s'%value,
                else:
                    print "unknown STREAM-INF attribute %s"%key
                    #raise ValueError("unknown STREAM-INF attribute %s"%key)
            print
        if choice==-1: choice=0
        #choice = int(raw_input("Selection? "))
        print 'choose %d'%choice
        url = urlparse.urljoin(redirurl, variants[choice][0])

    #queue = Queue.Queue(1024) # 1024 blocks of 4K each ~ 4MB buffer
    control = ['go']
    #thread = threading.Thread(target=player_pipe, args=(queue, control,file))
    #thread.start()
    last_seq = -1
    targetduration = 5
    changed = 0
    glsession=None
    if ':7777' in url:
        try:
            glsession=re.compile(':7777\/.*?m3u8.*?session=(.*?)&').findall(url)[0]
        except: 
            pass

    try:
        while 1==1:#thread.isAlive():
            if stopEvent and stopEvent.isSet():
                return
            medialist = list(handle_basic_m3u(url))
            playedSomething=False
            if medialist==None: return
            if None in medialist:
                # choose to start playback at the start, since this is a VOD stream
                pass
            else:
                # choose to start playback three files from the end, since this is a live stream
                medialist = medialist[-6:]
            #print 'medialist',medialist
            addsomewait=False
            for media in medialist:
                 
                if stopEvent and stopEvent.isSet():
                    return
                if media is None:
                    #queue.put(None, block=True)
                    return
                seq, encobj, duration, targetduration, media_url = media
                addsomewait=True
                if seq > last_seq:
                    #print 'downloading.............',url
                    
                    enc=None
                    if encobj:
                        codeurl,iv=encobj
                        key = download_file(codeurl)

                        if not USEDec==3:
                            enc = AES.new(key, AES.MODE_CBC, iv)
                        else:
                            ivb=array.array('B',iv)
                            keyb= array.array('B',key)
                            enc=python_aes.new(keyb, 2, ivb)
                        #enc=AESDecrypter.new(key, 2, iv)
                        
                    if glsession: media_url=media_url.replace(glsession,glsession[:-10]+''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)))
                    try:
                        for chunk in download_chunks(urlparse.urljoin(url, media_url),enc=encobj):
                            if stopEvent and stopEvent.isSet():
                                return
                            #print '1. chunk available %d'%len(chunk)
                            if enc: 
                                 if not USEDec==3:
                                    chunk = enc.decrypt(chunk)
                                 else:
                                    chunkb=array.array('B',chunk)
                                    chunk = enc.decrypt(chunkb)
                                    chunk="".join(map(chr, chunk))
                            #if enc: chunk = enc.decrypt(chunk,key,'CBC')
                            #print '2. chunk done %d'%len(chunk)
                            if dumpfile: dumpfile.write(chunk)
                            #queue.put(chunk, block=True)
                            send_back(chunk,file)
                            #print '3. chunk available %d'%len(chunk)
                        last_seq = seq
                        changed = 1
                        playedSomething=True
                    except: pass
            
            '''if changed == 1:
                # initial minimum reload delay
                time.sleep(duration)
            elif changed == 0:
                # first attempt
                time.sleep(targetduration*0.5)
            elif changed == -1:
                # second attempt
                time.sleep(targetduration*1.5)
            else:
                # third attempt and beyond
                time.sleep(targetduration*3.0)
            
            changed -= 1
            '''
            if not playedSomething:
                xbmc.sleep(2000+ (3000 if addsomewait else 0))
    except:
        control[0] = 'stop'
        raise
Example #6
0
def handle_basic_m3u(url):
    global iv
    global key
    global USEDec
    seq = 1
    enc = None
    nextlen = 5
    duration = 5
    targetduration = 5
    for line in gen_m3u(url):
        if line.startswith("#EXT"):
            tag, attribs = parse_m3u_tag(line)
            if tag == "#EXTINF":
                duration = float(attribs[0])
            elif tag == "#EXT-X-TARGETDURATION":
                assert len(attribs) == 1, "too many attribs in EXT-X-TARGETDURATION"
                targetduration = int(attribs[0])
                pass
            elif tag == "#EXT-X-MEDIA-SEQUENCE":
                assert len(attribs) == 1, "too many attribs in EXT-X-MEDIA-SEQUENCE"
                seq = int(attribs[0])
            elif tag == "#EXT-X-KEY":
                attribs = parse_kv(attribs, ("METHOD", "URI", "IV"))
                assert "METHOD" in attribs, "expected METHOD in EXT-X-KEY"
                if attribs["METHOD"] == "NONE":
                    assert "URI" not in attribs, "EXT-X-KEY: METHOD=NONE, but URI found"
                    assert "IV" not in attribs, "EXT-X-KEY: METHOD=NONE, but IV found"
                    enc = None
                elif attribs["METHOD"] == "AES-128":
                    assert "URI" in attribs, "EXT-X-KEY: METHOD=AES-128, but no URI found"
                    # from Crypto.Cipher import AES
                    key = download_file(attribs["URI"].strip('"'))
                    assert len(key) == 16, "EXT-X-KEY: downloaded key file has bad length"
                    if "IV" in attribs:
                        assert attribs["IV"].lower().startswith("0x"), "EXT-X-KEY: IV attribute has bad format"
                        iv = attribs["IV"][2:].zfill(32).decode("hex")
                        assert len(iv) == 16, "EXT-X-KEY: IV attribute has bad length"
                    else:
                        iv = "\0" * 8 + struct.pack(">Q", seq)

                    if not USEDec == 3:
                        enc = AES.new(key, AES.MODE_CBC, iv)
                    else:
                        ivb = array.array("B", iv)
                        keyb = array.array("B", key)
                        enc = python_aes.new(keyb, 2, ivb)
                    # enc = AES_CBC(key)
                    # print key
                    # print iv
                    # enc=AESDecrypter.new(key, 2, iv)
                else:
                    assert False, "EXT-X-KEY: METHOD=%s unknown" % attribs["METHOD"]
            elif tag == "#EXT-X-PROGRAM-DATE-TIME":
                assert len(attribs) == 1, "too many attribs in EXT-X-PROGRAM-DATE-TIME"
                # TODO parse attribs[0] as ISO8601 date/time
                pass
            elif tag == "#EXT-X-ALLOW-CACHE":
                # XXX deliberately ignore
                pass
            elif tag == "#EXT-X-ENDLIST":
                assert not attribs
                yield None
                return
            elif tag == "#EXT-X-STREAM-INF":
                raise ValueError("don't know how to handle EXT-X-STREAM-INF in basic playlist")
            elif tag == "#EXT-X-DISCONTINUITY":
                assert not attribs
                print "[warn] discontinuity in stream"
            elif tag == "#EXT-X-VERSION":
                assert len(attribs) == 1
                if int(attribs[0]) > SUPPORTED_VERSION:
                    print "[warn] file version %s exceeds supported version %d; some things might be broken" % (
                        attribs[0],
                        SUPPORTED_VERSION,
                    )
            # else:
            #    raise ValueError("tag %s not known"%tag)
        else:
            yield (seq, enc, duration, targetduration, line)
            seq += 1
Example #7
0
def downloadInternal(url,file,maxbitrate=0,stopEvent=None , callbackpath="",callbackparam="", testing=False):
    global key
    global iv
    global USEDec
    global cookieJar
    global clientHeader
    global nsplayer
    global callbackDRM
    if stopEvent and stopEvent.isSet():
        return False
    dumpfile = None
    #dumpfile=open('c:\\temp\\myfile.mp4',"wb")
    variants = []
    variant = None
    veryfirst=True
    #url check if requires redirect
    redirurl=url
    utltext=''
    try:
        print 'going for url  ',url
        res=getUrl(url,returnres=True )
        print 'here ', res
        if res.history: 
            print 'history is',res.history
            redirurl=res.url
            url=redirurl
        utltext=res.text
        res.close()
        if testing: return True
    except: traceback.print_exc()
    print 'redirurl',redirurl
    if 'EXT-X-STREAM-INF' in utltext:
        try:
            for line in gen_m3u(redirurl):
                if line.startswith('#EXT'):
                    tag, attribs = parse_m3u_tag(line)
                    if tag == '#EXT-X-STREAM-INF':
                        variant = attribs
                elif variant:
                    variants.append((line, variant))
                    variant = None
            print 'variants',variants
            if len(variants)==0: url=redirurl
            if len(variants) == 1:
                url = urlparse.urljoin(redirurl, variants[0][0])
            elif len(variants) >= 2:
                print "More than one variant of the stream was provided."

                choice=-1
                lastbitrate=0
                print 'maxbitrate',maxbitrate
                for i, (vurl, vattrs) in enumerate(variants):
                    print i, vurl,
                    for attr in vattrs:
                        key, value = attr.split('=')
                        key = key.strip()
                        value = value.strip().strip('"')
                        if key == 'BANDWIDTH':
                            print 'bitrate %.2f kbps'%(int(value)/1024.0)
                            if int(value)<=int(maxbitrate) and int(value)>lastbitrate:
                                choice=i
                                lastbitrate=int(value)
                        elif key == 'PROGRAM-ID':
                            print 'program %s'%value,
                        elif key == 'CODECS':
                            print 'codec %s'%value,
                        elif key == 'RESOLUTION':
                            print 'resolution %s'%value,
                        else:
                            print "unknown STREAM-INF attribute %s"%key
                            #raise ValueError("unknown STREAM-INF attribute %s"%key)
                    print
                if choice==-1: choice=0
                #choice = int(raw_input("Selection? "))
                print 'choose %d'%choice
                url = urlparse.urljoin(redirurl, variants[choice][0])
        except: 
            
            raise

    
    print 'final url',url
    last_seq = -1
    targetduration = 5
    changed = 0

    fails=0
    maxfails=5
    nsplayer=False
    print 'inside HLS RETRY'
    try:

        #file.write(b'FLV\x01')
        #file.write(b'\x01')
        #file.write(b'\x00\x00\x00\x09')
        # FLV File body
        #file.write(b'\x00\x00\x00\x09')
        while 1==1:#thread.isAlive():
            
            reconnect=False
            vod=False
            if fails>maxfails: 
                #stopEvent.set()
                break
            if stopEvent and stopEvent.isSet():
                return False
            try:
                medialist = list(handle_basic_m3u(url))
                if len(medialist)==0: raise Exception('empty m3u8')
                print medialist
                if testing: return True
            except Exception as inst:
                print 'here in exp',inst
                print fails
                fails+=1
                if testing and fails>6: return False
                
                if testing==False and '403' in repr(inst).lower() and callbackpath and len(callbackpath)>0:
                    print 'callback'
                    import importlib, os
                    foldername=os.path.sep.join(callbackpath.split(os.path.sep)[:-1])
                    urlnew=''
                    if foldername not in sys.path:
                        sys.path.append(foldername)
                    try:
                        callbackfilename= callbackpath.split(os.path.sep)[-1].split('.')[0]
                        callbackmodule = importlib.import_module(callbackfilename)
                        urlnew,cjnew=callbackmodule.f4mcallback(callbackparam, 1, inst, cookieJar , url, clientHeader)
                    except: traceback.print_exc()
                    if urlnew and len(urlnew)>0 and urlnew.startswith('http'):
                        print 'got new url',url
                        url=urlnew
                        cookieJar= cjnew
                        continue
                    else: 
                        return
                if '403' in repr(inst).lower() or '401' in repr(inst).lower():
                    if fails in [1,4,5,10,15,19]: 
                        nsplayer=True 
                    else:
                        nsplayer=False
                    print 'nsplayer',nsplayer
                    xbmc.sleep(1000)
                continue 

            nsplayer=False
            playedSomething=False
            if medialist==None: return

                ## choose to start playback three files from the end, since this is a live stream
                #medialist = medialist[-6:]
            #print 'medialist',medialist
            addsomewait=False
            lastKeyUrl=""
            lastkey=None
            playedduration=0
            st=time.time()
            for media in medialist:
                 
                if stopEvent and stopEvent.isSet():
                    return False
                if media is None:
                    #send_back('G'+chr(254)+chr(255)+('\0'*1), file)
                    #queue.put(None, block=True)
                    
                    
                    if stopEvent:
                        print 'set events'
                        stopEvent.set()
                    return False
                seq, encobj, duration, targetduration, media_url,vod = media
                
                if seq > last_seq:
                    #print 'downloading.............',url
                    
                    enc=None
                    if encobj:
                        
                        codeurl,iv=encobj
                        if codeurl<>lastKeyUrl:
                            if codeurl.startswith('http'):
                                key = download_file(codeurl)
                            elif codeurl.startswith('LSDRMCallBack$'):
                                key=callbackDRM.DRMCallback(codeurl.split('LSDRMCallBack$')[1],url)
                            else:
                                key = codeurl
                            codeurl=lastKeyUrl
                        else:
                            key=lastkey
                        lastkey=key   
                        if not USEDec==3:
                            enc = AES.new(key, AES.MODE_CBC, iv)
                        else:
                            ivb=array.array('B',iv)
                            keyb= array.array('B',key)
                            enc=python_aes.new(keyb, 2, ivb)
                        #enc=AESDecrypter.new(key, 2, iv)
                    try:
                        data=None
                        try:
                            print 'downloading', urlparse.urljoin(url, media_url)
                            #for chunk in download_chunks(urlparse.urljoin(url, media_url)):
                            for chunk in download_chunks(media_url):
                                if stopEvent and stopEvent.isSet():
                                    return False
                                print 'sending chunk', len(chunk)
                                if enc: 
                                 if not USEDec==3:
                                    chunk = enc.decrypt(chunk)
                                 else:
                                    chunkb=array.array('B',chunk)
                                    chunk = enc.decrypt(chunkb)
                                    chunk="".join(map(chr, chunk))
                                send_back(chunk,file)
                                data="send"
                            playedduration+=duration
                            addsomewait=True
                      
                        except Exception as inst:
                            print 'xxxx',repr(inst)
                            if 'forcibly closed' in repr(inst): 
                                print 'returning'
                                return False
                        if stopEvent and stopEvent.isSet():
                            return False

                        if data and len(data)>0:# chunk in download_chunks(urlparse.urljoin(url, media_url),enc=encobj):

                            #if not veryfirst:
                            #    if dumpfile: dumpfile.write(chunk)
                            #    #queue.put(chunk, block=True)
                            #    send_back(data,file)
                            #    #print '3. chunk available %d'%len(chunk)
                            veryfirst=False
                            last_seq = seq
                            changed = 1
                            playedSomething=True
                            fails=0
                            maxfails=20
                        else:
                            reconnect=True
                            fails+=1
                            break
                    except: pass
            
            if vod: return True
            if playedSomething == 1:
                # initial minimum reload delay
                timetowait=int(targetduration - (time.time()-st))#
                if (timetowait)>0:
                    print 'sleeping because targetduration',timetowait
                    for t in range(0,timetowait):
                        xbmc.sleep(1000)
                        print 'sleeep for 1sec',t
                        if stopEvent and stopEvent.isSet():
                            return False
            '''elif changed == 0:
                # first attempt
                time.sleep(targetduration*0.5)
            elif changed == -1:
                # second attempt
                time.sleep(targetduration*1.5)
            else:
                # third attempt and beyond
                time.sleep(targetduration*3.0)
            
            changed -= 1
            '''
            
            if not playedSomething:
                xbmc.sleep(3000+ (3000 if addsomewait else 0))
            
    except:
        
        raise