Search in sources :

Example 46 with Format

use of com.google.android.exoplayer2.Format in project ExoPlayer by google.

the class DefaultTrackSelector method selectTextTrack.

// Text track selection implementation.
protected TrackSelection selectTextTrack(TrackGroupArray groups, int[][] formatSupport, String preferredTextLanguage, String preferredAudioLanguage, boolean exceedRendererCapabilitiesIfNecessary) {
    TrackGroup selectedGroup = null;
    int selectedTrackIndex = 0;
    int selectedTrackScore = 0;
    for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) {
        TrackGroup trackGroup = groups.get(groupIndex);
        int[] trackFormatSupport = formatSupport[groupIndex];
        for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
            if (isSupported(trackFormatSupport[trackIndex], exceedRendererCapabilitiesIfNecessary)) {
                Format format = trackGroup.getFormat(trackIndex);
                boolean isDefault = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0;
                boolean isForced = (format.selectionFlags & C.SELECTION_FLAG_FORCED) != 0;
                int trackScore;
                if (formatHasLanguage(format, preferredTextLanguage)) {
                    if (isDefault) {
                        trackScore = 6;
                    } else if (!isForced) {
                        // Prefer non-forced to forced if a preferred text language has been specified. Where
                        // both are provided the non-forced track will usually contain the forced subtitles as
                        // a subset.
                        trackScore = 5;
                    } else {
                        trackScore = 4;
                    }
                } else if (isDefault) {
                    trackScore = 3;
                } else if (isForced) {
                    if (formatHasLanguage(format, preferredAudioLanguage)) {
                        trackScore = 2;
                    } else {
                        trackScore = 1;
                    }
                } else {
                    // Track should not be selected.
                    continue;
                }
                if (isSupported(trackFormatSupport[trackIndex], false)) {
                    trackScore += WITHIN_RENDERER_CAPABILITIES_BONUS;
                }
                if (trackScore > selectedTrackScore) {
                    selectedGroup = trackGroup;
                    selectedTrackIndex = trackIndex;
                    selectedTrackScore = trackScore;
                }
            }
        }
    }
    return selectedGroup == null ? null : new FixedTrackSelection(selectedGroup, selectedTrackIndex);
}
Also used : Format(com.google.android.exoplayer2.Format) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) Point(android.graphics.Point)

Example 47 with Format

use of com.google.android.exoplayer2.Format in project ExoPlayer by google.

the class DefaultTrackSelector method selectFixedVideoTrack.

private static TrackSelection selectFixedVideoTrack(TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, int maxVideoBitrate, int viewportWidth, int viewportHeight, boolean orientationMayChange, boolean exceedConstraintsIfNecessary, boolean exceedRendererCapabilitiesIfNecessary) {
    TrackGroup selectedGroup = null;
    int selectedTrackIndex = 0;
    int selectedTrackScore = 0;
    int selectedBitrate = Format.NO_VALUE;
    int selectedPixelCount = Format.NO_VALUE;
    for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) {
        TrackGroup trackGroup = groups.get(groupIndex);
        List<Integer> selectedTrackIndices = getViewportFilteredTrackIndices(trackGroup, viewportWidth, viewportHeight, orientationMayChange);
        int[] trackFormatSupport = formatSupport[groupIndex];
        for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
            if (isSupported(trackFormatSupport[trackIndex], exceedRendererCapabilitiesIfNecessary)) {
                Format format = trackGroup.getFormat(trackIndex);
                boolean isWithinConstraints = selectedTrackIndices.contains(trackIndex) && (format.width == Format.NO_VALUE || format.width <= maxVideoWidth) && (format.height == Format.NO_VALUE || format.height <= maxVideoHeight) && (format.bitrate == Format.NO_VALUE || format.bitrate <= maxVideoBitrate);
                if (!isWithinConstraints && !exceedConstraintsIfNecessary) {
                    // Track should not be selected.
                    continue;
                }
                int trackScore = isWithinConstraints ? 2 : 1;
                if (isSupported(trackFormatSupport[trackIndex], false)) {
                    trackScore += WITHIN_RENDERER_CAPABILITIES_BONUS;
                }
                boolean selectTrack = trackScore > selectedTrackScore;
                if (trackScore == selectedTrackScore) {
                    // Use the pixel count as a tie breaker (or bitrate if pixel counts are tied). If we're
                    // within constraints prefer a higher pixel count (or bitrate), else prefer a lower
                    // count (or bitrate). If still tied then prefer the first track (i.e. the one that's
                    // already selected).
                    int comparisonResult;
                    int formatPixelCount = format.getPixelCount();
                    if (formatPixelCount != selectedPixelCount) {
                        comparisonResult = compareFormatValues(format.getPixelCount(), selectedPixelCount);
                    } else {
                        comparisonResult = compareFormatValues(format.bitrate, selectedBitrate);
                    }
                    selectTrack = isWithinConstraints ? comparisonResult > 0 : comparisonResult < 0;
                }
                if (selectTrack) {
                    selectedGroup = trackGroup;
                    selectedTrackIndex = trackIndex;
                    selectedTrackScore = trackScore;
                    selectedBitrate = format.bitrate;
                    selectedPixelCount = format.getPixelCount();
                }
            }
        }
    }
    return selectedGroup == null ? null : new FixedTrackSelection(selectedGroup, selectedTrackIndex);
}
Also used : Format(com.google.android.exoplayer2.Format) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) Point(android.graphics.Point)

Example 48 with Format

use of com.google.android.exoplayer2.Format in project ExoPlayer by google.

the class DefaultTrackSelector method getViewportFilteredTrackIndices.

// Viewport size util methods.
private static List<Integer> getViewportFilteredTrackIndices(TrackGroup group, int viewportWidth, int viewportHeight, boolean orientationMayChange) {
    // Initially include all indices.
    ArrayList<Integer> selectedTrackIndices = new ArrayList<>(group.length);
    for (int i = 0; i < group.length; i++) {
        selectedTrackIndices.add(i);
    }
    if (viewportWidth == Integer.MAX_VALUE || viewportHeight == Integer.MAX_VALUE) {
        // Viewport dimensions not set. Return the full set of indices.
        return selectedTrackIndices;
    }
    int maxVideoPixelsToRetain = Integer.MAX_VALUE;
    for (int i = 0; i < group.length; i++) {
        Format format = group.getFormat(i);
        // We'll discard formats of higher resolution.
        if (format.width > 0 && format.height > 0) {
            Point maxVideoSizeInViewport = getMaxVideoSizeInViewport(orientationMayChange, viewportWidth, viewportHeight, format.width, format.height);
            int videoPixels = format.width * format.height;
            if (format.width >= (int) (maxVideoSizeInViewport.x * FRACTION_TO_CONSIDER_FULLSCREEN) && format.height >= (int) (maxVideoSizeInViewport.y * FRACTION_TO_CONSIDER_FULLSCREEN) && videoPixels < maxVideoPixelsToRetain) {
                maxVideoPixelsToRetain = videoPixels;
            }
        }
    }
    // filter out formats with unknown dimensions, since we have some whose dimensions are known.
    if (maxVideoPixelsToRetain != Integer.MAX_VALUE) {
        for (int i = selectedTrackIndices.size() - 1; i >= 0; i--) {
            Format format = group.getFormat(selectedTrackIndices.get(i));
            int pixelCount = format.getPixelCount();
            if (pixelCount == Format.NO_VALUE || pixelCount > maxVideoPixelsToRetain) {
                selectedTrackIndices.remove(i);
            }
        }
    }
    return selectedTrackIndices;
}
Also used : Format(com.google.android.exoplayer2.Format) ArrayList(java.util.ArrayList) Point(android.graphics.Point) Point(android.graphics.Point)

Example 49 with Format

use of com.google.android.exoplayer2.Format in project ExoPlayer by google.

the class TsExtractorTest method testCustomPesReader.

public void testCustomPesReader() throws Exception {
    CustomTsPayloadReaderFactory factory = new CustomTsPayloadReaderFactory(true, false);
    TsExtractor tsExtractor = new TsExtractor(TsExtractor.MODE_NORMAL, new TimestampAdjuster(0), factory);
    FakeExtractorInput input = new FakeExtractorInput.Builder().setData(TestUtil.getByteArray(getInstrumentation(), "ts/sample.ts")).setSimulateIOErrors(false).setSimulateUnknownLength(false).setSimulatePartialReads(false).build();
    FakeExtractorOutput output = new FakeExtractorOutput();
    tsExtractor.init(output);
    PositionHolder seekPositionHolder = new PositionHolder();
    int readResult = Extractor.RESULT_CONTINUE;
    while (readResult != Extractor.RESULT_END_OF_INPUT) {
        readResult = tsExtractor.read(input, seekPositionHolder);
    }
    CustomEsReader reader = factory.esReader;
    assertEquals(2, reader.packetsRead);
    TrackOutput trackOutput = reader.getTrackOutput();
    assertTrue(trackOutput == output.trackOutputs.get(257));
    assertEquals(Format.createTextSampleFormat("1/257", "mime", null, 0, 0, "und", null, 0), ((FakeTrackOutput) trackOutput).format);
}
Also used : FakeExtractorInput(com.google.android.exoplayer2.testutil.FakeExtractorInput) PositionHolder(com.google.android.exoplayer2.extractor.PositionHolder) TimestampAdjuster(com.google.android.exoplayer2.util.TimestampAdjuster) FakeExtractorOutput(com.google.android.exoplayer2.testutil.FakeExtractorOutput) TrackOutput(com.google.android.exoplayer2.extractor.TrackOutput) FakeTrackOutput(com.google.android.exoplayer2.testutil.FakeTrackOutput)

Example 50 with Format

use of com.google.android.exoplayer2.Format in project ExoPlayer by google.

the class H265Reader method parseMediaFormat.

private static Format parseMediaFormat(String formatId, NalUnitTargetBuffer vps, NalUnitTargetBuffer sps, NalUnitTargetBuffer pps) {
    // Build codec-specific data.
    byte[] csd = new byte[vps.nalLength + sps.nalLength + pps.nalLength];
    System.arraycopy(vps.nalData, 0, csd, 0, vps.nalLength);
    System.arraycopy(sps.nalData, 0, csd, vps.nalLength, sps.nalLength);
    System.arraycopy(pps.nalData, 0, csd, vps.nalLength + sps.nalLength, pps.nalLength);
    // Parse the SPS NAL unit, as per H.265/HEVC (2014) 7.3.2.2.1.
    ParsableNalUnitBitArray bitArray = new ParsableNalUnitBitArray(sps.nalData, 0, sps.nalLength);
    // NAL header, sps_video_parameter_set_id
    bitArray.skipBits(40 + 4);
    int maxSubLayersMinus1 = bitArray.readBits(3);
    // sps_temporal_id_nesting_flag
    bitArray.skipBits(1);
    // profile_tier_level(1, sps_max_sub_layers_minus1)
    // if (profilePresentFlag) {...}
    bitArray.skipBits(88);
    // general_level_idc
    bitArray.skipBits(8);
    int toSkip = 0;
    for (int i = 0; i < maxSubLayersMinus1; i++) {
        if (bitArray.readBit()) {
            // sub_layer_profile_present_flag[i]
            toSkip += 89;
        }
        if (bitArray.readBit()) {
            // sub_layer_level_present_flag[i]
            toSkip += 8;
        }
    }
    bitArray.skipBits(toSkip);
    if (maxSubLayersMinus1 > 0) {
        bitArray.skipBits(2 * (8 - maxSubLayersMinus1));
    }
    // sps_seq_parameter_set_id
    bitArray.readUnsignedExpGolombCodedInt();
    int chromaFormatIdc = bitArray.readUnsignedExpGolombCodedInt();
    if (chromaFormatIdc == 3) {
        // separate_colour_plane_flag
        bitArray.skipBits(1);
    }
    int picWidthInLumaSamples = bitArray.readUnsignedExpGolombCodedInt();
    int picHeightInLumaSamples = bitArray.readUnsignedExpGolombCodedInt();
    if (bitArray.readBit()) {
        // conformance_window_flag
        int confWinLeftOffset = bitArray.readUnsignedExpGolombCodedInt();
        int confWinRightOffset = bitArray.readUnsignedExpGolombCodedInt();
        int confWinTopOffset = bitArray.readUnsignedExpGolombCodedInt();
        int confWinBottomOffset = bitArray.readUnsignedExpGolombCodedInt();
        // H.265/HEVC (2014) Table 6-1
        int subWidthC = chromaFormatIdc == 1 || chromaFormatIdc == 2 ? 2 : 1;
        int subHeightC = chromaFormatIdc == 1 ? 2 : 1;
        picWidthInLumaSamples -= subWidthC * (confWinLeftOffset + confWinRightOffset);
        picHeightInLumaSamples -= subHeightC * (confWinTopOffset + confWinBottomOffset);
    }
    // bit_depth_luma_minus8
    bitArray.readUnsignedExpGolombCodedInt();
    // bit_depth_chroma_minus8
    bitArray.readUnsignedExpGolombCodedInt();
    int log2MaxPicOrderCntLsbMinus4 = bitArray.readUnsignedExpGolombCodedInt();
    // for (i = sps_sub_layer_ordering_info_present_flag ? 0 : sps_max_sub_layers_minus1; ...)
    for (int i = bitArray.readBit() ? 0 : maxSubLayersMinus1; i <= maxSubLayersMinus1; i++) {
        // sps_max_dec_pic_buffering_minus1[i]
        bitArray.readUnsignedExpGolombCodedInt();
        // sps_max_num_reorder_pics[i]
        bitArray.readUnsignedExpGolombCodedInt();
        // sps_max_latency_increase_plus1[i]
        bitArray.readUnsignedExpGolombCodedInt();
    }
    // log2_min_luma_coding_block_size_minus3
    bitArray.readUnsignedExpGolombCodedInt();
    // log2_diff_max_min_luma_coding_block_size
    bitArray.readUnsignedExpGolombCodedInt();
    // log2_min_luma_transform_block_size_minus2
    bitArray.readUnsignedExpGolombCodedInt();
    // log2_diff_max_min_luma_transform_block_size
    bitArray.readUnsignedExpGolombCodedInt();
    // max_transform_hierarchy_depth_inter
    bitArray.readUnsignedExpGolombCodedInt();
    // max_transform_hierarchy_depth_intra
    bitArray.readUnsignedExpGolombCodedInt();
    // if (scaling_list_enabled_flag) { if (sps_scaling_list_data_present_flag) {...}}
    boolean scalingListEnabled = bitArray.readBit();
    if (scalingListEnabled && bitArray.readBit()) {
        skipScalingList(bitArray);
    }
    // amp_enabled_flag (1), sample_adaptive_offset_enabled_flag (1)
    bitArray.skipBits(2);
    if (bitArray.readBit()) {
        // pcm_enabled_flag
        // pcm_sample_bit_depth_luma_minus1 (4), pcm_sample_bit_depth_chroma_minus1 (4)
        bitArray.skipBits(8);
        // log2_min_pcm_luma_coding_block_size_minus3
        bitArray.readUnsignedExpGolombCodedInt();
        // log2_diff_max_min_pcm_luma_coding_block_size
        bitArray.readUnsignedExpGolombCodedInt();
        // pcm_loop_filter_disabled_flag
        bitArray.skipBits(1);
    }
    // Skips all short term reference picture sets.
    skipShortTermRefPicSets(bitArray);
    if (bitArray.readBit()) {
        // num_long_term_ref_pics_sps
        for (int i = 0; i < bitArray.readUnsignedExpGolombCodedInt(); i++) {
            int ltRefPicPocLsbSpsLength = log2MaxPicOrderCntLsbMinus4 + 4;
            // lt_ref_pic_poc_lsb_sps[i], used_by_curr_pic_lt_sps_flag[i]
            bitArray.skipBits(ltRefPicPocLsbSpsLength + 1);
        }
    }
    // sps_temporal_mvp_enabled_flag, strong_intra_smoothing_enabled_flag
    bitArray.skipBits(2);
    float pixelWidthHeightRatio = 1;
    if (bitArray.readBit()) {
        // vui_parameters_present_flag
        if (bitArray.readBit()) {
            // aspect_ratio_info_present_flag
            int aspectRatioIdc = bitArray.readBits(8);
            if (aspectRatioIdc == NalUnitUtil.EXTENDED_SAR) {
                int sarWidth = bitArray.readBits(16);
                int sarHeight = bitArray.readBits(16);
                if (sarWidth != 0 && sarHeight != 0) {
                    pixelWidthHeightRatio = (float) sarWidth / sarHeight;
                }
            } else if (aspectRatioIdc < NalUnitUtil.ASPECT_RATIO_IDC_VALUES.length) {
                pixelWidthHeightRatio = NalUnitUtil.ASPECT_RATIO_IDC_VALUES[aspectRatioIdc];
            } else {
                Log.w(TAG, "Unexpected aspect_ratio_idc value: " + aspectRatioIdc);
            }
        }
    }
    return Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_H265, null, Format.NO_VALUE, Format.NO_VALUE, picWidthInLumaSamples, picHeightInLumaSamples, Format.NO_VALUE, Collections.singletonList(csd), Format.NO_VALUE, pixelWidthHeightRatio, null);
}
Also used : ParsableNalUnitBitArray(com.google.android.exoplayer2.util.ParsableNalUnitBitArray)

Aggregations

Format (com.google.android.exoplayer2.Format)38 Point (android.graphics.Point)8 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)6 DataSpec (com.google.android.exoplayer2.upstream.DataSpec)5 ArrayList (java.util.ArrayList)5 SuppressLint (android.annotation.SuppressLint)4 MediaFormat (android.media.MediaFormat)4 ParserException (com.google.android.exoplayer2.ParserException)4 DrmInitData (com.google.android.exoplayer2.drm.DrmInitData)4 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)4 TrackOutput (com.google.android.exoplayer2.extractor.TrackOutput)3 Representation (com.google.android.exoplayer2.source.dash.manifest.Representation)3 SchemeData (com.google.android.exoplayer2.drm.DrmInitData.SchemeData)2 MediaCodecInfo (com.google.android.exoplayer2.mediacodec.MediaCodecInfo)2 Metadata (com.google.android.exoplayer2.metadata.Metadata)2 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)2 ContainerMediaChunk (com.google.android.exoplayer2.source.chunk.ContainerMediaChunk)2 AdaptationSet (com.google.android.exoplayer2.source.dash.manifest.AdaptationSet)2 RangedUri (com.google.android.exoplayer2.source.dash.manifest.RangedUri)2 SingleSegmentBase (com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase)2