xref: /aosp_15_r20/frameworks/av/media/libdatasource/MediaHTTP.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "MediaHTTP"
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include <datasource/MediaHTTP.h>
22*ec779b8eSAndroid Build Coastguard Worker 
23*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ALooper.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/FoundationUtils.h>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaHTTPConnection.h>
28*ec779b8eSAndroid Build Coastguard Worker 
29*ec779b8eSAndroid Build Coastguard Worker namespace android {
30*ec779b8eSAndroid Build Coastguard Worker 
MediaHTTP(const sp<MediaHTTPConnection> & conn)31*ec779b8eSAndroid Build Coastguard Worker MediaHTTP::MediaHTTP(const sp<MediaHTTPConnection> &conn)
32*ec779b8eSAndroid Build Coastguard Worker     : mInitCheck((conn != NULL) ? OK : NO_INIT),
33*ec779b8eSAndroid Build Coastguard Worker       mHTTPConnection(conn),
34*ec779b8eSAndroid Build Coastguard Worker       mCachedSizeValid(false),
35*ec779b8eSAndroid Build Coastguard Worker       mCachedSize(0ll) {
36*ec779b8eSAndroid Build Coastguard Worker }
37*ec779b8eSAndroid Build Coastguard Worker 
~MediaHTTP()38*ec779b8eSAndroid Build Coastguard Worker MediaHTTP::~MediaHTTP() {
39*ec779b8eSAndroid Build Coastguard Worker }
40*ec779b8eSAndroid Build Coastguard Worker 
connect(const char * uri,const KeyedVector<String8,String8> * headers,off64_t)41*ec779b8eSAndroid Build Coastguard Worker status_t MediaHTTP::connect(
42*ec779b8eSAndroid Build Coastguard Worker         const char *uri,
43*ec779b8eSAndroid Build Coastguard Worker         const KeyedVector<String8, String8> *headers,
44*ec779b8eSAndroid Build Coastguard Worker         off64_t /* offset */) {
45*ec779b8eSAndroid Build Coastguard Worker     if (mInitCheck != OK) {
46*ec779b8eSAndroid Build Coastguard Worker         return mInitCheck;
47*ec779b8eSAndroid Build Coastguard Worker     }
48*ec779b8eSAndroid Build Coastguard Worker 
49*ec779b8eSAndroid Build Coastguard Worker     KeyedVector<String8, String8> extHeaders;
50*ec779b8eSAndroid Build Coastguard Worker     if (headers != NULL) {
51*ec779b8eSAndroid Build Coastguard Worker         extHeaders = *headers;
52*ec779b8eSAndroid Build Coastguard Worker     }
53*ec779b8eSAndroid Build Coastguard Worker 
54*ec779b8eSAndroid Build Coastguard Worker     if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {
55*ec779b8eSAndroid Build Coastguard Worker         extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
56*ec779b8eSAndroid Build Coastguard Worker     }
57*ec779b8eSAndroid Build Coastguard Worker 
58*ec779b8eSAndroid Build Coastguard Worker     mLastURI = uri;
59*ec779b8eSAndroid Build Coastguard Worker     // reconnect() calls with uri == old mLastURI.c_str(), which gets zapped
60*ec779b8eSAndroid Build Coastguard Worker     // as part of the above assignment. Ensure no accidental later use.
61*ec779b8eSAndroid Build Coastguard Worker     uri = NULL;
62*ec779b8eSAndroid Build Coastguard Worker 
63*ec779b8eSAndroid Build Coastguard Worker     bool success = mHTTPConnection->connect(mLastURI.c_str(), &extHeaders);
64*ec779b8eSAndroid Build Coastguard Worker 
65*ec779b8eSAndroid Build Coastguard Worker     mLastHeaders = extHeaders;
66*ec779b8eSAndroid Build Coastguard Worker 
67*ec779b8eSAndroid Build Coastguard Worker     mCachedSizeValid = false;
68*ec779b8eSAndroid Build Coastguard Worker 
69*ec779b8eSAndroid Build Coastguard Worker     if (success) {
70*ec779b8eSAndroid Build Coastguard Worker         AString sanitized = uriDebugString(mLastURI);
71*ec779b8eSAndroid Build Coastguard Worker         mName = String8::format("MediaHTTP(%s)", sanitized.c_str());
72*ec779b8eSAndroid Build Coastguard Worker     }
73*ec779b8eSAndroid Build Coastguard Worker 
74*ec779b8eSAndroid Build Coastguard Worker     return success ? OK : UNKNOWN_ERROR;
75*ec779b8eSAndroid Build Coastguard Worker }
76*ec779b8eSAndroid Build Coastguard Worker 
close()77*ec779b8eSAndroid Build Coastguard Worker void MediaHTTP::close() {
78*ec779b8eSAndroid Build Coastguard Worker     disconnect();
79*ec779b8eSAndroid Build Coastguard Worker }
80*ec779b8eSAndroid Build Coastguard Worker 
disconnect()81*ec779b8eSAndroid Build Coastguard Worker void MediaHTTP::disconnect() {
82*ec779b8eSAndroid Build Coastguard Worker     mName = String8("MediaHTTP(<disconnected>)");
83*ec779b8eSAndroid Build Coastguard Worker     if (mInitCheck != OK) {
84*ec779b8eSAndroid Build Coastguard Worker         return;
85*ec779b8eSAndroid Build Coastguard Worker     }
86*ec779b8eSAndroid Build Coastguard Worker 
87*ec779b8eSAndroid Build Coastguard Worker     mHTTPConnection->disconnect();
88*ec779b8eSAndroid Build Coastguard Worker }
89*ec779b8eSAndroid Build Coastguard Worker 
initCheck() const90*ec779b8eSAndroid Build Coastguard Worker status_t MediaHTTP::initCheck() const {
91*ec779b8eSAndroid Build Coastguard Worker     return mInitCheck;
92*ec779b8eSAndroid Build Coastguard Worker }
93*ec779b8eSAndroid Build Coastguard Worker 
readAt(off64_t offset,void * data,size_t size)94*ec779b8eSAndroid Build Coastguard Worker ssize_t MediaHTTP::readAt(off64_t offset, void *data, size_t size) {
95*ec779b8eSAndroid Build Coastguard Worker     if (mInitCheck != OK) {
96*ec779b8eSAndroid Build Coastguard Worker         return mInitCheck;
97*ec779b8eSAndroid Build Coastguard Worker     }
98*ec779b8eSAndroid Build Coastguard Worker 
99*ec779b8eSAndroid Build Coastguard Worker     int64_t startTimeUs = ALooper::GetNowUs();
100*ec779b8eSAndroid Build Coastguard Worker 
101*ec779b8eSAndroid Build Coastguard Worker     size_t numBytesRead = 0;
102*ec779b8eSAndroid Build Coastguard Worker     while (numBytesRead < size) {
103*ec779b8eSAndroid Build Coastguard Worker         size_t copy = size - numBytesRead;
104*ec779b8eSAndroid Build Coastguard Worker 
105*ec779b8eSAndroid Build Coastguard Worker         if (copy > 64 * 1024) {
106*ec779b8eSAndroid Build Coastguard Worker             // limit the buffer sizes transferred across binder boundaries
107*ec779b8eSAndroid Build Coastguard Worker             // to avoid spurious transaction failures.
108*ec779b8eSAndroid Build Coastguard Worker             copy = 64 * 1024;
109*ec779b8eSAndroid Build Coastguard Worker         }
110*ec779b8eSAndroid Build Coastguard Worker 
111*ec779b8eSAndroid Build Coastguard Worker         ssize_t n = mHTTPConnection->readAt(
112*ec779b8eSAndroid Build Coastguard Worker                 offset + numBytesRead, (uint8_t *)data + numBytesRead, copy);
113*ec779b8eSAndroid Build Coastguard Worker 
114*ec779b8eSAndroid Build Coastguard Worker         if (n < 0) {
115*ec779b8eSAndroid Build Coastguard Worker             return n;
116*ec779b8eSAndroid Build Coastguard Worker         } else if (n == 0) {
117*ec779b8eSAndroid Build Coastguard Worker             break;
118*ec779b8eSAndroid Build Coastguard Worker         }
119*ec779b8eSAndroid Build Coastguard Worker 
120*ec779b8eSAndroid Build Coastguard Worker         numBytesRead += n;
121*ec779b8eSAndroid Build Coastguard Worker     }
122*ec779b8eSAndroid Build Coastguard Worker 
123*ec779b8eSAndroid Build Coastguard Worker     int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
124*ec779b8eSAndroid Build Coastguard Worker 
125*ec779b8eSAndroid Build Coastguard Worker     addBandwidthMeasurement(numBytesRead, delayUs);
126*ec779b8eSAndroid Build Coastguard Worker 
127*ec779b8eSAndroid Build Coastguard Worker     return numBytesRead;
128*ec779b8eSAndroid Build Coastguard Worker }
129*ec779b8eSAndroid Build Coastguard Worker 
getSize(off64_t * size)130*ec779b8eSAndroid Build Coastguard Worker status_t MediaHTTP::getSize(off64_t *size) {
131*ec779b8eSAndroid Build Coastguard Worker     if (mInitCheck != OK) {
132*ec779b8eSAndroid Build Coastguard Worker         return mInitCheck;
133*ec779b8eSAndroid Build Coastguard Worker     }
134*ec779b8eSAndroid Build Coastguard Worker 
135*ec779b8eSAndroid Build Coastguard Worker     // Caching the returned size so that it stays valid even after a
136*ec779b8eSAndroid Build Coastguard Worker     // disconnect. NuCachedSource2 relies on this.
137*ec779b8eSAndroid Build Coastguard Worker 
138*ec779b8eSAndroid Build Coastguard Worker     if (!mCachedSizeValid) {
139*ec779b8eSAndroid Build Coastguard Worker         mCachedSize = mHTTPConnection->getSize();
140*ec779b8eSAndroid Build Coastguard Worker         mCachedSizeValid = true;
141*ec779b8eSAndroid Build Coastguard Worker     }
142*ec779b8eSAndroid Build Coastguard Worker 
143*ec779b8eSAndroid Build Coastguard Worker     *size = mCachedSize;
144*ec779b8eSAndroid Build Coastguard Worker 
145*ec779b8eSAndroid Build Coastguard Worker     return *size < 0 ? *size : static_cast<status_t>(OK);
146*ec779b8eSAndroid Build Coastguard Worker }
147*ec779b8eSAndroid Build Coastguard Worker 
flags()148*ec779b8eSAndroid Build Coastguard Worker uint32_t MediaHTTP::flags() {
149*ec779b8eSAndroid Build Coastguard Worker     return kWantsPrefetching | kIsHTTPBasedSource;
150*ec779b8eSAndroid Build Coastguard Worker }
151*ec779b8eSAndroid Build Coastguard Worker 
reconnectAtOffset(off64_t offset)152*ec779b8eSAndroid Build Coastguard Worker status_t MediaHTTP::reconnectAtOffset(off64_t offset) {
153*ec779b8eSAndroid Build Coastguard Worker     return connect(mLastURI.c_str(), &mLastHeaders, offset);
154*ec779b8eSAndroid Build Coastguard Worker }
155*ec779b8eSAndroid Build Coastguard Worker 
156*ec779b8eSAndroid Build Coastguard Worker 
getUri()157*ec779b8eSAndroid Build Coastguard Worker String8 MediaHTTP::getUri() {
158*ec779b8eSAndroid Build Coastguard Worker     if (mInitCheck != OK) {
159*ec779b8eSAndroid Build Coastguard Worker         return String8();
160*ec779b8eSAndroid Build Coastguard Worker     }
161*ec779b8eSAndroid Build Coastguard Worker 
162*ec779b8eSAndroid Build Coastguard Worker     String8 uri;
163*ec779b8eSAndroid Build Coastguard Worker     if (OK == mHTTPConnection->getUri(&uri)) {
164*ec779b8eSAndroid Build Coastguard Worker         return uri;
165*ec779b8eSAndroid Build Coastguard Worker     }
166*ec779b8eSAndroid Build Coastguard Worker     return String8(mLastURI.c_str());
167*ec779b8eSAndroid Build Coastguard Worker }
168*ec779b8eSAndroid Build Coastguard Worker 
getMIMEType() const169*ec779b8eSAndroid Build Coastguard Worker String8 MediaHTTP::getMIMEType() const {
170*ec779b8eSAndroid Build Coastguard Worker     if (mInitCheck != OK) {
171*ec779b8eSAndroid Build Coastguard Worker         return String8("application/octet-stream");
172*ec779b8eSAndroid Build Coastguard Worker     }
173*ec779b8eSAndroid Build Coastguard Worker 
174*ec779b8eSAndroid Build Coastguard Worker     String8 mimeType;
175*ec779b8eSAndroid Build Coastguard Worker     status_t err = mHTTPConnection->getMIMEType(&mimeType);
176*ec779b8eSAndroid Build Coastguard Worker 
177*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
178*ec779b8eSAndroid Build Coastguard Worker         return String8("application/octet-stream");
179*ec779b8eSAndroid Build Coastguard Worker     }
180*ec779b8eSAndroid Build Coastguard Worker 
181*ec779b8eSAndroid Build Coastguard Worker     return mimeType;
182*ec779b8eSAndroid Build Coastguard Worker }
183*ec779b8eSAndroid Build Coastguard Worker 
184*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
185