'Parse formats from ISM manifest.
References:
1. [MS-SSTR]: Smooth Streaming Protocol,
https://msdn.microsoft.com/en-us/library/ff469518.aspx'

def _parse_ism_formats(self, ism_doc, ism_url, ism_id=None):

    if ((ism_doc.get(u'IsLive') == u'TRUE') or (ism_doc.find(u'Protection') is not None)):
        return []
    duration = int(ism_doc.attrib[u'Duration'])
    timescale = (int_or_none(ism_doc.get(u'TimeScale')) or 10000000)
    formats = []
    for stream in ism_doc.findall(u'StreamIndex'):
        stream_type = stream.get(u'Type')
        if (stream_type not in (u'video', u'audio')):
            continue
        url_pattern = stream.attrib[u'Url']
        stream_timescale = (int_or_none(stream.get(u'TimeScale')) or timescale)
        stream_name = stream.get(u'Name')
        for track in stream.findall(u'QualityLevel'):
            fourcc = track.get(u'FourCC')
            if (fourcc not in (u'H264', u'AVC1', u'AACL')):
                self.report_warning((u'%s    is    not    a    supported    codec' % fourcc))
                continue
            tbr = (int(track.attrib[u'Bitrate']) // 1000)
            width = int_or_none((track.get(u'MaxWidth') or track.get(u'Width')))
            height = int_or_none((track.get(u'MaxHeight') or track.get(u'Height')))
            sampling_rate = int_or_none(track.get(u'SamplingRate'))
            track_url_pattern = re.sub(u'{[Bb]itrate}', track.attrib[u'Bitrate'], url_pattern)
            track_url_pattern = compat_urlparse.urljoin(ism_url, track_url_pattern)
            fragments = []
            fragment_ctx = {u'time': 0}
            stream_fragments = stream.findall(u'c')
            for (stream_fragment_index, stream_fragment) in enumerate(stream_fragments):
                fragment_ctx[u'time'] = (int_or_none(stream_fragment.get(u't')) or fragment_ctx[u'time'])
                fragment_repeat = (int_or_none(stream_fragment.get(u'r')) or 1)
                fragment_ctx[u'duration'] = int_or_none(stream_fragment.get(u'd'))
                if (not fragment_ctx[u'duration']):
                    try:
                        next_fragment_time = int(stream_fragment[(stream_fragment_index + 1)].attrib[u't'])
                    except IndexError:
                        next_fragment_time = duration
                    fragment_ctx[u'duration'] = ((next_fragment_time - fragment_ctx[u'time']) / fragment_repeat)
                for _ in range(fragment_repeat):
                    fragments.append({u'url': re.sub(u'{start[    _]time}', compat_str(fragment_ctx[u'time']), track_url_pattern), u'duration': (fragment_ctx[u'duration'] / stream_timescale)})
                    fragment_ctx[u'time'] += fragment_ctx[u'duration']
            format_id = []
            if ism_id:
                format_id.append(ism_id)
            if stream_name:
                format_id.append(stream_name)
            format_id.append(compat_str(tbr))
            formats.append({u'format_id': u'-'.join(format_id), u'url': ism_url, u'manifest_url': ism_url, u'ext': (u'ismv' if (stream_type == u'video') else u'isma'), u'width': width, u'height': height, u'tbr': tbr, u'asr': sampling_rate, u'vcodec': (u'none' if (stream_type == u'audio') else fourcc), u'acodec': (u'none' if (stream_type == u'video') else fourcc), u'protocol': u'ism', u'fragments': fragments, u'_download_params': {u'duration': duration, u'timescale': stream_timescale, u'width': (width or 0), u'height': (height or 0), u'fourcc': fourcc, u'codec_private_data': track.get(u'CodecPrivateData'), u'sampling_rate': sampling_rate, u'channels': int_or_none(track.get(u'Channels', 2)), u'bits_per_sample': int_or_none(track.get(u'BitsPerSample', 16)), u'nal_unit_length_field': int_or_none(track.get(u'NALUnitLengthField', 4))}})
    return formats
