1f933441648ef6a71dee783d733aac17b9508b452Andreas Huber/*
2f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *
4f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * you may not use this file except in compliance with the License.
6f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * You may obtain a copy of the License at
7f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *
8f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *
10f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Unless required by applicable law or agreed to in writing, software
11f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * See the License for the specific language governing permissions and
14f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * limitations under the License.
15f933441648ef6a71dee783d733aac17b9508b452Andreas Huber */
16f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
17f933441648ef6a71dee783d733aac17b9508b452Andreas Huber//#define LOG_NDEBUG 0
18f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#define LOG_TAG "NuPlayerDecoder"
19f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <utils/Log.h>
20f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
21f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include "NuPlayerDecoder.h"
22f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
23f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
24f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ADebug.h>
255bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/foundation/AMessage.h>
26f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/ACodec.h>
27f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/MediaDefs.h>
28f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
29f933441648ef6a71dee783d733aac17b9508b452Andreas Hubernamespace android {
30f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
31f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Decoder::Decoder(
321173118eace0e9e347cb007f0da817cee87579edGlenn Kasten        const sp<AMessage> &notify,
331173118eace0e9e347cb007f0da817cee87579edGlenn Kasten        const sp<NativeWindowWrapper> &nativeWindow)
34f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    : mNotify(notify),
351173118eace0e9e347cb007f0da817cee87579edGlenn Kasten      mNativeWindow(nativeWindow) {
36f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
37f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
38f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Decoder::~Decoder() {
39f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
40f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
41840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubervoid NuPlayer::Decoder::configure(const sp<AMessage> &format) {
42f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(mCodec == NULL);
43f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
44840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    AString mime;
45840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK(format->findString("mime", &mime));
46f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
47f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyMsg =
48f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        new AMessage(kWhatCodecNotify, id());
49f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
50840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mCSDIndex = 0;
51840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (size_t i = 0;; ++i) {
52840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        sp<ABuffer> csd;
53840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (!format->findBuffer(StringPrintf("csd-%d", i).c_str(), &csd)) {
54840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            break;
55840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
56840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
57840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mCSD.push(csd);
58840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
59f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
601173118eace0e9e347cb007f0da817cee87579edGlenn Kasten    if (mNativeWindow != NULL) {
611173118eace0e9e347cb007f0da817cee87579edGlenn Kasten        format->setObject("native-window", mNativeWindow);
62f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
63f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
64078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    // Current video decoders do not return from OMX_FillThisBuffer
65078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    // quickly, violating the OpenMAX specs, until that is remedied
66078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    // we need to invest in an extra looper to free the main event
67078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    // queue.
68840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    bool needDedicatedLooper = !strncasecmp(mime.c_str(), "video/", 6);
69078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
700523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    mFormat = format;
7100f4951088805442e86ff9c2a20ddad79fc2410aAndreas Huber    mCodec = new ACodec;
72078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
73078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    if (needDedicatedLooper && mCodecLooper == NULL) {
74078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mCodecLooper = new ALooper;
75078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mCodecLooper->setName("NuPlayerDecoder");
76078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
77078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
78078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
79078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    (needDedicatedLooper ? mCodecLooper : looper())->registerHandler(mCodec);
80f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
8100f4951088805442e86ff9c2a20ddad79fc2410aAndreas Huber    mCodec->setNotificationMessage(notifyMsg);
8200f4951088805442e86ff9c2a20ddad79fc2410aAndreas Huber    mCodec->initiateSetup(format);
83f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
84f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
85f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
86f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    switch (msg->what()) {
87f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatCodecNotify:
88f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
89f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t what;
90f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(msg->findInt32("what", &what));
91f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
92f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            if (what == ACodec::kWhatFillThisBuffer) {
93f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                onFillThisBuffer(msg);
94f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            } else {
95f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                sp<AMessage> notify = mNotify->dup();
96f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                notify->setMessage("codec-request", msg);
97f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                notify->post();
98f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
99f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
100f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
101f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
102f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        default:
103f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            TRESPASS();
104f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
105f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
106f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
107f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
108f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Decoder::onFillThisBuffer(const sp<AMessage> &msg) {
109f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> reply;
110f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findMessage("reply", &reply));
111f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
112f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#if 0
1132d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    sp<ABuffer> outBuffer;
1142d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    CHECK(msg->findBuffer("buffer", &outBuffer));
115f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#else
116f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<ABuffer> outBuffer;
117f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#endif
118f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
119f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mCSDIndex < mCSD.size()) {
120f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        outBuffer = mCSD.editItemAt(mCSDIndex++);
121f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        outBuffer->meta()->setInt64("timeUs", 0);
122f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1232d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber        reply->setBuffer("buffer", outBuffer);
124f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        reply->post();
125f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
126f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
127f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
128f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
129f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setMessage("codec-request", msg);
130f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->post();
131f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
132f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
133f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Decoder::signalFlush() {
134f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mCodec != NULL) {
135f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mCodec->signalFlush();
136f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
137f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
138f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
139f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Decoder::signalResume() {
140f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mCodec != NULL) {
141f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mCodec->signalResume();
142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1453831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Hubervoid NuPlayer::Decoder::initiateShutdown() {
1463831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    if (mCodec != NULL) {
1473831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber        mCodec->initiateShutdown();
1483831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    }
1493831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber}
1503831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
1510523da8f16557a85395da86ab76be6d8cb771da0Robert Shihbool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const {
1520523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    if (targetFormat == NULL) {
1530523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        return true;
1540523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    }
1550523da8f16557a85395da86ab76be6d8cb771da0Robert Shih
1560523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    AString mime;
1570523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    if (!targetFormat->findString("mime", &mime)) {
1580523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        return false;
1590523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    }
1600523da8f16557a85395da86ab76be6d8cb771da0Robert Shih
1610523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
1620523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        // field-by-field comparison
1630523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
1640523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
1650523da8f16557a85395da86ab76be6d8cb771da0Robert Shih            int32_t oldVal, newVal;
1660523da8f16557a85395da86ab76be6d8cb771da0Robert Shih            if (!mFormat->findInt32(keys[i], &oldVal) || !targetFormat->findInt32(keys[i], &newVal)
1670523da8f16557a85395da86ab76be6d8cb771da0Robert Shih                    || oldVal != newVal) {
1680523da8f16557a85395da86ab76be6d8cb771da0Robert Shih                return false;
1690523da8f16557a85395da86ab76be6d8cb771da0Robert Shih            }
1700523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        }
1710523da8f16557a85395da86ab76be6d8cb771da0Robert Shih
1720523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        sp<ABuffer> oldBuf, newBuf;
1730523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        if (mFormat->findBuffer("csd-0", &oldBuf) && targetFormat->findBuffer("csd-0", &newBuf)) {
1740523da8f16557a85395da86ab76be6d8cb771da0Robert Shih            if (oldBuf->size() != newBuf->size()) {
1750523da8f16557a85395da86ab76be6d8cb771da0Robert Shih                return false;
1760523da8f16557a85395da86ab76be6d8cb771da0Robert Shih            }
1770523da8f16557a85395da86ab76be6d8cb771da0Robert Shih            return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
1780523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        }
1790523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    }
1800523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    return false;
1810523da8f16557a85395da86ab76be6d8cb771da0Robert Shih}
1820523da8f16557a85395da86ab76be6d8cb771da0Robert Shih
1830523da8f16557a85395da86ab76be6d8cb771da0Robert Shihbool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
1840523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    if (mFormat == NULL) {
1850523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        return false;
1860523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    }
1870523da8f16557a85395da86ab76be6d8cb771da0Robert Shih
1880523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    if (targetFormat == NULL) {
1890523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        return true;
1900523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    }
1910523da8f16557a85395da86ab76be6d8cb771da0Robert Shih
1920523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    AString oldMime, newMime;
1930523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    if (!mFormat->findString("mime", &oldMime)
1940523da8f16557a85395da86ab76be6d8cb771da0Robert Shih            || !targetFormat->findString("mime", &newMime)
1950523da8f16557a85395da86ab76be6d8cb771da0Robert Shih            || !(oldMime == newMime)) {
1960523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        return false;
1970523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    }
1980523da8f16557a85395da86ab76be6d8cb771da0Robert Shih
1990523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
2000523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    bool seamless;
2010523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    if (audio) {
2020523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        seamless = supportsSeamlessAudioFormatChange(targetFormat);
2030523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    } else {
2040523da8f16557a85395da86ab76be6d8cb771da0Robert Shih        seamless = mCodec != NULL && mCodec->isConfiguredForAdaptivePlayback();
2050523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    }
2060523da8f16557a85395da86ab76be6d8cb771da0Robert Shih
2070523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
2080523da8f16557a85395da86ab76be6d8cb771da0Robert Shih    return seamless;
2090523da8f16557a85395da86ab76be6d8cb771da0Robert Shih}
2100523da8f16557a85395da86ab76be6d8cb771da0Robert Shih
211f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}  // namespace android
212f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
213