2 * Copyright 2012 Michael Chen <omxcodec@gmail.com>
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define LOG_TAG "FFMPEG"
18 #include <utils/Log.h>
21 #include "ffmpeg_source.h"
23 #include <media/stagefright/DataSource.h>
28 #include "libavformat/url.h"
37 void set(DataSource *s) { mSource = s; }
39 int read(unsigned char *buf, size_t size);
40 int64_t seek(int64_t pos);
44 sp<DataSource> mSource;
48 int FFSource::init_check()
50 if (mSource->initCheck() != OK) {
51 ALOGE("FFSource initCheck failed");
58 int FFSource::read(unsigned char *buf, size_t size)
62 n = mSource->readAt(mOffset, buf, size);
63 if (n == UNKNOWN_ERROR) {
64 ALOGE("FFSource readAt failed");
65 return AVERROR(errno);
74 int64_t FFSource::seek(int64_t pos)
80 off64_t FFSource::getSize()
84 if (mSource->getSize(&sz) != OK) {
85 ALOGE("FFSource getSize failed");
86 return AVERROR(errno);
92 /////////////////////////////////////////////////////////////////
94 static int android_open(URLContext *h, const char *url, int flags __unused)
96 // the url in form of "android-source:<DataSource Ptr>",
97 // the DataSource Pointer passed by the ffmpeg extractor
98 DataSource *source = NULL;
99 char url_check[PATH_MAX] = {0};
101 ALOGV("android source begin open");
104 ALOGE("android url is null!");
108 ALOGV("android open, url: %s", url);
109 sscanf(url + strlen("android-source:"), "%p", &source);
111 ALOGE("ffmpeg open data source error! (invalid source)");
115 snprintf(url_check, sizeof(url_check), "android-source:%p",
118 if (strcmp(url_check, url) != 0) {
120 String8 uri = source->getUri();
122 ALOGE("ffmpeg open data source error! (source uri)");
126 snprintf(url_check, sizeof(url_check), "android-source:%p|file:%s",
127 source, uri.string());
129 if (strcmp(url_check, url) != 0) {
130 ALOGE("ffmpeg open data source error! (url check)");
135 ALOGV("ffmpeg open android data source success, source ptr: %p", source);
137 reinterpret_cast<FFSource *>(h->priv_data)->set(source);
139 ALOGV("android source open success");
143 static int android_read(URLContext *h, unsigned char *buf, int size)
145 FFSource* ffs = (FFSource *)h->priv_data;
146 return ffs->read(buf, size);
149 static int android_write(URLContext *h __unused, const unsigned char *buf __unused, int size __unused)
154 static int64_t android_seek(URLContext *h, int64_t pos, int whence)
156 FFSource* ffs = (FFSource*)h->priv_data;
158 if (whence == AVSEEK_SIZE) {
159 return ffs->getSize();
166 static int android_close(URLContext *h)
168 ALOGV("android source close");
169 reinterpret_cast<FFSource *>(h->priv_data)->set(NULL);
173 static int android_get_handle(URLContext *h)
175 return (intptr_t)h->priv_data;
178 static int android_check(URLContext *h, int mask)
180 FFSource* ffs = (FFSource*)h->priv_data;
182 /* url_check does not guarantee url_open will be called
183 * (and actually it is not designed to do so)
184 * If url_open is not called before url_check called, ffs
185 * will be null, and we will assume everything is ok.
187 if (ffs && (ffs->init_check() < 0))
188 return AVERROR(EACCES); // FIXME
190 return (mask & AVIO_FLAG_READ);
193 extern "C" URLProtocol ff_android_protocol;
195 void ffmpeg_register_android_source()
197 if (ff_android_protocol.name) return;
199 ff_android_protocol.name = "android-source";
200 ff_android_protocol.url_open = android_open;
201 ff_android_protocol.url_read = android_read;
202 ff_android_protocol.url_write = android_write;
203 ff_android_protocol.url_seek = android_seek;
204 ff_android_protocol.url_close = android_close;
205 ff_android_protocol.url_get_file_handle = android_get_handle;
206 ff_android_protocol.url_check = android_check;
207 ff_android_protocol.priv_data_size = sizeof(FFSource);
210 } // namespace android