{"action":"created","comment":{"url":"https://api.github.com/repos/google/ExoPlayer/pulls/comments/32703997","id":32703997,"diff_hunk":"@@ -0,0 +1,293 @@\n+/*\n+ * Copyright (C) 2014 The Android Open Source Project\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *      http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+package com.google.android.exoplayer.extractor.ts;\n+\n+import com.google.android.exoplayer.C;\n+import com.google.android.exoplayer.MediaFormat;\n+import com.google.android.exoplayer.extractor.TrackOutput;\n+import com.google.android.exoplayer.util.CodecSpecificDataUtil;\n+import com.google.android.exoplayer.util.MimeTypes;\n+import com.google.android.exoplayer.util.ParsableBitArray;\n+import com.google.android.exoplayer.util.ParsableByteArray;\n+\n+import android.util.Pair;\n+\n+import java.util.Collections;\n+\n+/**\n+   * Parses a continuous MPEG Audio byte stream and extracts individual\n+   * frames.\n+   */\n+/* package */ public class MpaReader extends ElementaryStreamReader {\n+\n+    private static final int STATE_FINDING_SYNC = 0;\n+    private static final int STATE_READING_HEADER = 1;\n+    private static final int STATE_READING_SAMPLE = 2;\n+\n+    private static final int HEADER_SIZE = 4;\n+    private static final int CRC_SIZE = 2;\n+\n+    private final ParsableBitArray mpaScratch;\n+\n+    private int state;\n+    private int bytesRead;\n+\n+    // Used to find the header.\n+    private boolean hasCrc;\n+\n+    // Used when parsing the header.\n+    private boolean hasOutputFormat;\n+    private long frameDurationUs;\n+    private int sampleSize;\n+\n+    // Used when reading the samples.\n+    private long timeUs;\n+\n+    //\n+    /**\n+     * sampling rates in hertz:\n+     *\n+     *     @index MPEG Version ID\n+     *     @index sampling rate index\n+     */\n+\n+    private static final int[][] MPA_SAMPLING_RATES = new int[][] {\n+            {11025, 12000,  8000},    // MPEG 2.5\n+            {    0,     0,     0},    // reserved\n+            {22050, 24000, 16000},    // MPEG 2\n+            {44100, 48000, 32000}     // MPEG 1\n+    };\n+\n+    /**\n+     * bitrates:\n+     *\n+     *     @index LSF\n+     *     @index Layer\n+     *     @index bitrate index\n+     */\n+\n+    private static final int[][][] MPA_BITRATES = new int[][][] {\n+            { // MPEG 1\n+                    // Layer1\n+                    {  0,  32,  64,  96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448},\n+                    // Layer2\n+                    {  0,  32,  48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384},\n+                    // Layer3\n+                    {  0,  32,  40,  48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320}\n+            },\n+            { // MPEG 2, 2.5\n+                    // Layer1\n+                    {  0,  32,  48,  56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256},\n+                    // Layer2\n+                    {  0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160},\n+                    // Layer3\n+                    {  0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160}\n+            }\n+    };\n+\n+    /**\n+     * Samples per Frame:\n+     *\n+     *  @index LSF\n+     *  @index Layer\n+     */\n+\n+    private static final int[][] MPA_SAMPLES_PER_FRAME = new int[][] {\n+            {           // MPEG 1\n+                    384,   // Layer1\n+                    1152,   // Layer2\n+                    1152    // Layer3\n+            },\n+            {           // MPEG 2, 2.5\n+                    384,   // Layer1\n+                    1152,   // Layer2\n+                    576    // Layer3\n+            }\n+    };\n+\n+    /**\n+     * Coefficients (samples per frame / 8):\n+     *\n+     * @index = LSF\n+     * @index = Layer\n+     */\n+\n+    private static final int[][] MPA_COEFFICIENTS = new int[][] {\n+            {           // MPEG 1\n+                    12,    // Layer1\n+                    144,    // Layer2\n+                    144     // Layer3\n+            },\n+            {           // MPEG 2, 2.5\n+                    12,    // Layer1\n+                    144,    // Layer2\n+                    72     // Layer3\n+            }\n+    };\n+\n+    /**\n+     * slot size per layer:\n+     *\n+     * @index = Layer\n+     */\n+\n+    private static final int[] MPA_SLOT_SIZE = new int[] {\n+            4,          // Layer1\n+            1,          // Layer2\n+            1           // Layer3\n+    };\n+\n+    public MpaReader(TrackOutput output) {\n+        super(output);\n+        mpaScratch = new ParsableBitArray(new byte[HEADER_SIZE + CRC_SIZE]);\n+        state = STATE_FINDING_SYNC;\n+    }\n+\n+    @Override\n+    public void consume(ParsableByteArray data, long pesTimeUs, boolean startOfPacket) {\n+        if (startOfPacket) {\n+            timeUs = pesTimeUs;\n+        }\n+        while (data.bytesLeft() > 0) {\n+            switch (state) {\n+                case STATE_FINDING_SYNC:\n+                    if (skipToNextSync(data)) {\n+                        bytesRead = 0;\n+                        state = STATE_READING_HEADER;\n+                    }\n+                    break;\n+                case STATE_READING_HEADER:\n+                    int targetLength = hasCrc ? HEADER_SIZE + CRC_SIZE : HEADER_SIZE;\n+                    if (continueRead(data, mpaScratch.getData(), targetLength)) {\n+                        parseHeader();\n+                        bytesRead = targetLength;\n+                        state = STATE_READING_SAMPLE;\n+                    }\n+                    break;\n+                case STATE_READING_SAMPLE:\n+                    int bytesToRead = Math.min(data.bytesLeft(), sampleSize - bytesRead);\n+                    output.sampleData(data, bytesToRead);\n+                    bytesRead += bytesToRead;\n+                    if (bytesRead == sampleSize) {\n+                        output.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null);\n+                        timeUs += frameDurationUs;\n+                        bytesRead = 0;\n+                        state = STATE_FINDING_SYNC;\n+                    }\n+                    break;\n+            }\n+        }\n+    }\n+\n+    @Override\n+    public void packetFinished() {\n+        // Do nothing.\n+    }\n+\n+    /**\n+     * Continues a read from the provided {@code source} into a given {@code target}. It's assumed\n+     * that the data should be written into {@code target} starting from an offset of zero.\n+     *\n+     * @param source The source from which to read.\n+     * @param target The target into which data is to be read.\n+     * @param targetLength The target length of the read.\n+     * @return Whether the target length was reached.\n+     */\n+    private boolean continueRead(ParsableByteArray source, byte[] target, int targetLength) {\n+        int bytesToRead = Math.min(source.bytesLeft(), targetLength - bytesRead);\n+        source.readBytes(target, bytesRead, bytesToRead);\n+        bytesRead += bytesToRead;\n+        return bytesRead == targetLength;\n+    }\n+\n+    /**\n+     * Locates the next sync word, advancing the position to the byte that immediately follows it.\n+     * If a sync word was not located, the position is advanced to the limit.\n+     *\n+     * @param pesBuffer The buffer whose position should be advanced.\n+     * @return True if a sync word position was found. False otherwise.\n+     */\n+    private boolean skipToNextSync(ParsableByteArray pesBuffer) {\n+        byte[] mpaData = pesBuffer.data;\n+        int startOffset = pesBuffer.getPosition();\n+        int endOffset = pesBuffer.limit();\n+        for (int i = startOffset; i < endOffset - 1; i++) {\n+            int syncBits = ((mpaData[i] & 0xFF) << 8 ) | (mpaData[i + 1] & 0xFF);\n+            if ((syncBits & 0xFFF0) == 0xFFF0) {\n+                hasCrc = (mpaData[i + 1] & 0x1) == 0;\n+                pesBuffer.setPosition(i);\n+                return true;\n+            }\n+        }\n+        pesBuffer.setPosition(endOffset);\n+        return false;\n+    }\n+\n+    /**\n+     * Calculates MPEG Audio frame size\n+     *\n+     * @param layer The MPEG layer\n+     * @param LSF Low Sample rate Format (MPEG 2)\n+     * @param bitrate The bitrate in bits per second\n+     * @param samplesPerSec The sampling rate in hertz\n+     * @param -paddingSize\n+     * @return Frame size in bytes\n+     */\n+    private static int CalcMpaFrameSize (int layer, int LSF, int bitrate, int samplesPerSec, int paddingSize) {\n+        return (int)(Math.floor(MPA_COEFFICIENTS[LSF][layer] * bitrate / samplesPerSec) + paddingSize) * MPA_SLOT_SIZE[layer];\n+    }\n+\n+    /**\n+     * Parses the sample header.\n+     */\n+    private void parseHeader() {\n+        int headerLength = hasCrc ? HEADER_SIZE + CRC_SIZE : HEADER_SIZE;\n+\n+        if (!hasOutputFormat) {\n+            mpaScratch.setPosition(0);\n+            mpaScratch.skipBits(12);\n+            int isLSF = (!mpaScratch.readBit()) ? 1 : 0;\n+            int layer = mpaScratch.readBits(2) ^ 3;\n+            mpaScratch.skipBits(1);\n+            int audioObjectType = 32 + layer;\n+            int bitRate = MPA_BITRATES[isLSF][layer][mpaScratch.readBits(4)];\n+            int sampleRate = MPA_SAMPLING_RATES[3 - isLSF][mpaScratch.readBits(2)];","path":"library/src/main/java/com/google/android/exoplayer/extractor/ts/MpaReader.java","position":267,"original_position":267,"commit_id":"dd3a4a91394068349c5423505dbd81fd56d537e6","original_commit_id":"e5acc5a2c86466c26917f810deff2455f9b4272b","user":{"login":"optman","id":2323912,"avatar_url":"https://avatars.githubusercontent.com/u/2323912?v=3","gravatar_id":"","url":"https://api.github.com/users/optman","html_url":"https://github.com/optman","followers_url":"https://api.github.com/users/optman/followers","following_url":"https://api.github.com/users/optman/following{/other_user}","gists_url":"https://api.github.com/users/optman/gists{/gist_id}","starred_url":"https://api.github.com/users/optman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/optman/subscriptions","organizations_url":"https://api.github.com/users/optman/orgs","repos_url":"https://api.github.com/users/optman/repos","events_url":"https://api.github.com/users/optman/events{/privacy}","received_events_url":"https://api.github.com/users/optman/received_events","type":"User","site_admin":false},"body":"because the audio source is from FME live stream, i can only provide fragment of a frame. \r\n\r\nff e3 20 70 b8 0b e8 8b 67 1f ce 20 00 01 20 02 5c ad 80 00 00 e9 ff d1 69 f4 6d 7a 96 ee d6 ed 3c 6f ff ff c0 00 00 ad 34 49 35 55 5b 6a 5c db 96 c6 c0 07 2d 40 6f e8 c1 c7 a8 71 58 cf 31 86\r\n\r\nit seem that the header is correct! \r\n\r\nhttp://www.mp3-tech.org/programmer/frame_header.html\r\n  \r\n\r\n","created_at":"2015-06-18T07:15:17Z","updated_at":"2015-06-18T07:15:17Z","html_url":"https://github.com/google/ExoPlayer/pull/325#discussion_r32703997","pull_request_url":"https://api.github.com/repos/google/ExoPlayer/pulls/325","_links":{"self":{"href":"https://api.github.com/repos/google/ExoPlayer/pulls/comments/32703997"},"html":{"href":"https://github.com/google/ExoPlayer/pull/325#discussion_r32703997"},"pull_request":{"href":"https://api.github.com/repos/google/ExoPlayer/pulls/325"}}},"pull_request":{"url":"https://api.github.com/repos/google/ExoPlayer/pulls/325","id":30101927,"html_url":"https://github.com/google/ExoPlayer/pull/325","diff_url":"https://github.com/google/ExoPlayer/pull/325.diff","patch_url":"https://github.com/google/ExoPlayer/pull/325.patch","issue_url":"https://api.github.com/repos/google/ExoPlayer/issues/325","number":325,"state":"open","locked":false,"title":"Added MPEG audio support to TsExtractor","user":{"login":"tresvecesseis","id":10452415,"avatar_url":"https://avatars.githubusercontent.com/u/10452415?v=3","gravatar_id":"","url":"https://api.github.com/users/tresvecesseis","html_url":"https://github.com/tresvecesseis","followers_url":"https://api.github.com/users/tresvecesseis/followers","following_url":"https://api.github.com/users/tresvecesseis/following{/other_user}","gists_url":"https://api.github.com/users/tresvecesseis/gists{/gist_id}","starred_url":"https://api.github.com/users/tresvecesseis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tresvecesseis/subscriptions","organizations_url":"https://api.github.com/users/tresvecesseis/orgs","repos_url":"https://api.github.com/users/tresvecesseis/repos","events_url":"https://api.github.com/users/tresvecesseis/events{/privacy}","received_events_url":"https://api.github.com/users/tresvecesseis/received_events","type":"User","site_admin":false},"body":"This is the first try to support more formats in TsExtractor, it works properly with streams with only one audio track (same as current AAC support)","created_at":"2015-02-26T18:14:28Z","updated_at":"2015-06-18T07:15:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e29961fa175c125fb15099f67c1de64ebad0ff4f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/google/ExoPlayer/pulls/325/commits","review_comments_url":"https://api.github.com/repos/google/ExoPlayer/pulls/325/comments","review_comment_url":"https://api.github.com/repos/google/ExoPlayer/pulls/comments{/number}","comments_url":"https://api.github.com/repos/google/ExoPlayer/issues/325/comments","statuses_url":"https://api.github.com/repos/google/ExoPlayer/statuses/dd3a4a91394068349c5423505dbd81fd56d537e6","head":{"label":"tresvecesseis:dev","ref":"dev","sha":"dd3a4a91394068349c5423505dbd81fd56d537e6","user":{"login":"tresvecesseis","id":10452415,"avatar_url":"https://avatars.githubusercontent.com/u/10452415?v=3","gravatar_id":"","url":"https://api.github.com/users/tresvecesseis","html_url":"https://github.com/tresvecesseis","followers_url":"https://api.github.com/users/tresvecesseis/followers","following_url":"https://api.github.com/users/tresvecesseis/following{/other_user}","gists_url":"https://api.github.com/users/tresvecesseis/gists{/gist_id}","starred_url":"https://api.github.com/users/tresvecesseis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tresvecesseis/subscriptions","organizations_url":"https://api.github.com/users/tresvecesseis/orgs","repos_url":"https://api.github.com/users/tresvecesseis/repos","events_url":"https://api.github.com/users/tresvecesseis/events{/privacy}","received_events_url":"https://api.github.com/users/tresvecesseis/received_events","type":"User","site_admin":false},"repo":{"id":31380973,"name":"ExoPlayer","full_name":"tresvecesseis/ExoPlayer","owner":{"login":"tresvecesseis","id":10452415,"avatar_url":"https://avatars.githubusercontent.com/u/10452415?v=3","gravatar_id":"","url":"https://api.github.com/users/tresvecesseis","html_url":"https://github.com/tresvecesseis","followers_url":"https://api.github.com/users/tresvecesseis/followers","following_url":"https://api.github.com/users/tresvecesseis/following{/other_user}","gists_url":"https://api.github.com/users/tresvecesseis/gists{/gist_id}","starred_url":"https://api.github.com/users/tresvecesseis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tresvecesseis/subscriptions","organizations_url":"https://api.github.com/users/tresvecesseis/orgs","repos_url":"https://api.github.com/users/tresvecesseis/repos","events_url":"https://api.github.com/users/tresvecesseis/events{/privacy}","received_events_url":"https://api.github.com/users/tresvecesseis/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tresvecesseis/ExoPlayer","description":"An extensible media player for Android","fork":true,"url":"https://api.github.com/repos/tresvecesseis/ExoPlayer","forks_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/forks","keys_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/teams","hooks_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/hooks","issue_events_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/issues/events{/number}","events_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/events","assignees_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/assignees{/user}","branches_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/branches{/branch}","tags_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/tags","blobs_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/git/refs{/sha}","trees_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/statuses/{sha}","languages_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/languages","stargazers_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/stargazers","contributors_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/contributors","subscribers_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/subscribers","subscription_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/subscription","commits_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/commits{/sha}","git_commits_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/git/commits{/sha}","comments_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/comments{/number}","issue_comment_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/issues/comments{/number}","contents_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/contents/{+path}","compare_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/merges","archive_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/downloads","issues_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/issues{/number}","pulls_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/pulls{/number}","milestones_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/milestones{/number}","notifications_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/labels{/name}","releases_url":"https://api.github.com/repos/tresvecesseis/ExoPlayer/releases{/id}","created_at":"2015-02-26T18:07:23Z","updated_at":"2015-04-13T14:59:04Z","pushed_at":"2015-06-17T21:03:11Z","git_url":"git://github.com/tresvecesseis/ExoPlayer.git","ssh_url":"git@github.com:tresvecesseis/ExoPlayer.git","clone_url":"https://github.com/tresvecesseis/ExoPlayer.git","svn_url":"https://github.com/tresvecesseis/ExoPlayer","homepage":"","size":7509,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"dev"}},"base":{"label":"google:dev","ref":"dev","sha":"6c5af232303ccf8166c8d4bc8266984a8a5ced93","user":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"repo":{"id":20818126,"name":"ExoPlayer","full_name":"google/ExoPlayer","owner":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/google/ExoPlayer","description":"An extensible media player for Android","fork":false,"url":"https://api.github.com/repos/google/ExoPlayer","forks_url":"https://api.github.com/repos/google/ExoPlayer/forks","keys_url":"https://api.github.com/repos/google/ExoPlayer/keys{/key_id}","collaborators_url":"https://api.github.com/repos/google/ExoPlayer/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/google/ExoPlayer/teams","hooks_url":"https://api.github.com/repos/google/ExoPlayer/hooks","issue_events_url":"https://api.github.com/repos/google/ExoPlayer/issues/events{/number}","events_url":"https://api.github.com/repos/google/ExoPlayer/events","assignees_url":"https://api.github.com/repos/google/ExoPlayer/assignees{/user}","branches_url":"https://api.github.com/repos/google/ExoPlayer/branches{/branch}","tags_url":"https://api.github.com/repos/google/ExoPlayer/tags","blobs_url":"https://api.github.com/repos/google/ExoPlayer/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/google/ExoPlayer/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/google/ExoPlayer/git/refs{/sha}","trees_url":"https://api.github.com/repos/google/ExoPlayer/git/trees{/sha}","statuses_url":"https://api.github.com/repos/google/ExoPlayer/statuses/{sha}","languages_url":"https://api.github.com/repos/google/ExoPlayer/languages","stargazers_url":"https://api.github.com/repos/google/ExoPlayer/stargazers","contributors_url":"https://api.github.com/repos/google/ExoPlayer/contributors","subscribers_url":"https://api.github.com/repos/google/ExoPlayer/subscribers","subscription_url":"https://api.github.com/repos/google/ExoPlayer/subscription","commits_url":"https://api.github.com/repos/google/ExoPlayer/commits{/sha}","git_commits_url":"https://api.github.com/repos/google/ExoPlayer/git/commits{/sha}","comments_url":"https://api.github.com/repos/google/ExoPlayer/comments{/number}","issue_comment_url":"https://api.github.com/repos/google/ExoPlayer/issues/comments{/number}","contents_url":"https://api.github.com/repos/google/ExoPlayer/contents/{+path}","compare_url":"https://api.github.com/repos/google/ExoPlayer/compare/{base}...{head}","merges_url":"https://api.github.com/repos/google/ExoPlayer/merges","archive_url":"https://api.github.com/repos/google/ExoPlayer/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/google/ExoPlayer/downloads","issues_url":"https://api.github.com/repos/google/ExoPlayer/issues{/number}","pulls_url":"https://api.github.com/repos/google/ExoPlayer/pulls{/number}","milestones_url":"https://api.github.com/repos/google/ExoPlayer/milestones{/number}","notifications_url":"https://api.github.com/repos/google/ExoPlayer/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/google/ExoPlayer/labels{/name}","releases_url":"https://api.github.com/repos/google/ExoPlayer/releases{/id}","created_at":"2014-06-13T21:19:18Z","updated_at":"2015-06-18T06:31:24Z","pushed_at":"2015-06-17T21:03:11Z","git_url":"git://github.com/google/ExoPlayer.git","ssh_url":"git@github.com:google/ExoPlayer.git","clone_url":"https://github.com/google/ExoPlayer.git","svn_url":"https://github.com/google/ExoPlayer","homepage":"","size":13200,"stargazers_count":1431,"watchers_count":1431,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":487,"mirror_url":null,"open_issues_count":91,"forks":487,"open_issues":91,"watchers":1431,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/google/ExoPlayer/pulls/325"},"html":{"href":"https://github.com/google/ExoPlayer/pull/325"},"issue":{"href":"https://api.github.com/repos/google/ExoPlayer/issues/325"},"comments":{"href":"https://api.github.com/repos/google/ExoPlayer/issues/325/comments"},"review_comments":{"href":"https://api.github.com/repos/google/ExoPlayer/pulls/325/comments"},"review_comment":{"href":"https://api.github.com/repos/google/ExoPlayer/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/google/ExoPlayer/pulls/325/commits"},"statuses":{"href":"https://api.github.com/repos/google/ExoPlayer/statuses/dd3a4a91394068349c5423505dbd81fd56d537e6"}}}}