androidx / androidx/media

HLS Live streaming not combine audio and video

Open
#473 9 comments 0 reactions 1 assignee View on GitHub

@tianyif is already working on this.

Since Jun 26, 2023.

needs triage question
Dominant language
Java
Stars
3k
Forks
955
Avg merge
12d 14h
Merged PRs (30d)
2

Description

Hi, I have not been able to play HLS streaming properly for a long time. I searched for an answer to this problem, but could not find a similar case anywhere. The problem is that after loading the streaming I have audio or video only but never both together. It selects randomly.

I have tried to fix this in a number of ways:

  • Use MergeDatasource from one url (because i have only one url from server) with only different mime type.
  • Use Options:
    setAllowMultipleAdaptiveSelections(true)
    setAllowVideoMixedMimeTypeAdaptiveness(true)
    setAllowAudioMixedMimeTypeAdaptiveness(true)
  • Overriding and selecting one of the tracks

None of the ways helped. It always displayed either video or audio.

I will try to describe the process:
First I download the url for the video:

https://xyz.abc.com/hls-aes/event/1120190/3/0/livepkgr_e208/230622_1008S415_0345_XYZ/280-450-825/pl.m3u8?pcode=c115&uh=3cc49d68fb4c9b05cec31627a8c0f6ef&base=c115-live-geo900-xyz-hls.secure.footprint.net%2fhls-live&etime=20230622203703&grs=g111&key=ABCDEF

In the next step I get a reply with a manifest where the content type is - application/vnd.apple.mpegurl:
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:30435
#EXT-X-ALLOW-CACHE:NO
#EXT-X-VERSION:2
#EXT-X-TARGETDURATION:2
#EXT-X-KEY:METHOD=AES-128,URI="https://abc.xyz.com/hls-aes/key/1120190/3/0/101/key.bin",IV=ABCDEFGH
#EXTINF:2,
Num30435.ts
#EXTINF:2,
Num30436.ts
#EXTINF:2,
Num30437.ts
#EXTINF:2,
Num30438.ts
#EXTINF:2,
Num30439.ts

Num30435.ts is then downloaded, where the content type is:
video/MP2T.

The logs most strangely get different ones as well.

FIRST CASE -> When audio only
timeline [eventTime=0.69, mediaPos=4.00, window=0, period=0, periodCount=1, windowCount=1, reason=SOURCE_UPDATE] period [?] window [10.00, seekable=true, dynamic=true]

audioEnabled [eventTime=0.91, mediaPos=4.00, window=0, period=0]
tracks [eventTime=0.91, mediaPos=4.00, window=0, period=0]

group

  • Track:0, id=0, mimeType=audio/mp4a-latm, bitrate=280000, channels=1, sample_rate=22050, supported=YES
  • Track:1, id=1, mimeType=audio/mp4a-latm, bitrate=450000, channels=1, sample_rate=22050, supported=YES
  • Track:2, id=2, mimeType=audio/mp4a-latm, bitrate=825000, channels=1, sample_rate=22050, supported=YES

group

  • Track:0, id=null, mimeType=application/id3, supported=YES

Metadata

  • HlsTrackMetadataEntry
    downstreamFormat [eventTime=1.12, mediaPos=4.00, window=0, period=0, id=2, mimeType=null, bitrate=825000]
    audioDecoderInitialized [eventTime=1.34, mediaPos=4.00, window=0, period=0, c2.android.aac.decoder]
    audioInputFormat [eventTime=1.34, mediaPos=4.00, window=0, period=0, id=2, mimeType=audio/mp4a-latm, bitrate=825000, codecs=mp4a.40.2, channels=1, sample_rate=22050]
    state [eventTime=1.59, mediaPos=4.00, window=0, period=0, READY]
    isPlaying [eventTime=1.60, mediaPos=4.00, window=0, period=0, true]
    timeline [eventTime=3.27, mediaPos=3.55, window=0, period=0, periodCount=1, windowCount=1, reason=SOURCE_UPDATE]
  • period [?]
  • window [10.00, seekable=true, dynamic=true]

SECOND CASE -> When video only
videoEnabled [eventTime=0.53, mediaPos=4.00, window=0, period=0]
tracks [eventTime=0.53, mediaPos=4.00, window=0, period=0]

group

  • Track:0, id=0, mimeType=video/avc, bitrate=280000, supported=YES
  • Track:1, id=1, mimeType=video/avc, bitrate=450000, supported=YES
  • Track:2, id=2, mimeType=video/avc, bitrate=825000, supported=YES

group

  • Track:0, id=1/8219, mimeType=application/cea-608, supported=YES

group

  • Track:0, id=null, mimeType=application/id3, supported=YES

Metadata

  • HlsTrackMetadataEntry
    downstreamFormat [eventTime=0.71, mediaPos=4.00, window=0, period=0, id=2, mimeType=null, bitrate=825000]
    videoDecoderInitialized [eventTime=1.07, mediaPos=4.00, window=0, period=0, c2.qti.avc.decoder]
    videoInputFormat [eventTime=1.08, mediaPos=4.00, window=0, period=0, id=2, mimeType=video/avc, bitrate=825000, codecs=avc1.4D401F, res=1024x576]
    videoSize [eventTime=1.11, mediaPos=4.00, window=0, period=0, 1024, 576]
    renderedFirstFrame [eventTime=1.11, mediaPos=4.00, window=0, period=0, Surface(name=null)/@0xda67faf]
    state [eventTime=1.18, mediaPos=4.00, window=0, period=0, READY]
    isPlaying [eventTime=1.18, mediaPos=4.00, window=0, period=0, true]

Here is a code:

 private fun initPlayer() = with(binding) {
        val trackSelector = DefaultTrackSelector(this@VideoPlayerActivity).apply {
            setParameters(buildUponParameters()
                .setAllowMultipleAdaptiveSelections(true)
                .setAllowVideoMixedMimeTypeAdaptiveness(true)
                .setAllowAudioMixedMimeTypeAdaptiveness(true)
            )
        }
        player = ExoPlayer.Builder(this@VideoPlayerActivity).apply {
            setSeekBackIncrementMs(durationInMs)
            setSeekForwardIncrementMs(durationInMs)
            setTrackSelector(trackSelector)
        }.build().apply {
            playerExo.player = this
            addAnalyticsListener(EventLogger())
            addListener(playerListener)
            playWhenReady = isPlayerPlaying
            seekTo(currentWindow, playbackPosition)
            stream?.let {
                val mediaDataSourceFactory: DataSource.Factory = DefaultHttpDataSource.Factory().apply {
                    setUserAgent(
                        Util.getUserAgent(
                            this@VideoPlayerActivity,
                            "MY_APP_NAME"
                        )
                    )
                    val bandwidthMeter = DefaultBandwidthMeter.Builder(this@VideoPlayerActivity)
                        .setResetOnNetworkTypeChange(false)
                        .build()
                    setTransferListener(bandwidthMeter)
                }
                val hlsOtherExtractorFactory: HlsExtractorFactory = DefaultHlsExtractorFactory(
                    DefaultTsPayloadReaderFactory.FLAG_ALLOW_NON_IDR_KEYFRAMES, true
                )

                val mediaSource: MediaSource = HlsMediaSource.Factory(mediaDataSourceFactory)
                    .setAllowChunklessPreparation(false)
                    .setExtractorFactory(hlsOtherExtractorFactory)
                    .createMediaSource(
                        MediaItem.Builder()
                            .setUri(it)
                            .setMimeType(MimeTypes.APPLICATION_M3U8)
                            //.setMimeType(MimeTypes.VIDEO_MP2T)
                            .build()
                    )

                setMediaSource(mediaSource)
                prepare()
            }
        }
    }

This problem does not occur on the old system player using the VideoView.class. Streaming looks fine.

Tested on:

  • Huawei P9,
  • One Plus 10T
  • Samsung M12 Galaxy

I would be grateful for any help!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.