OSDN Git Service

add ffmpeg heuristic decoder.
[android-x86/external-stagefright-plugins.git] / utils / ffmpeg_source.cpp
1 /*
2  * Copyright 2012 Michael Chen <omxcodec@gmail.com>
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #define LOG_NDEBUG 0
17 #define LOG_TAG "FFMPEG"
18 #include <utils/Log.h>
19
20 #include <stdlib.h>
21
22 #include <media/stagefright/DataSource.h>
23
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28 #include "config.h"
29 #include "libavformat/url.h"
30
31 #ifdef __cplusplus
32 }
33 #endif
34
35 namespace android {
36
37 class FFSource
38 {
39 public:
40     FFSource(DataSource *source);
41     int init_check();
42     int read(unsigned char *buf, size_t size);
43     int64_t seek(int64_t pos);
44     off64_t getSize();
45     ~FFSource();
46 protected:
47     sp<DataSource> mSource;
48     int64_t mOffset;
49 };
50
51 FFSource::FFSource(DataSource *source)
52     : mSource(source),
53       mOffset(0)
54 {
55 }
56
57 FFSource::~FFSource()
58 {
59         mSource = NULL;
60 }
61
62 int FFSource::init_check()
63 {
64     if (mSource->initCheck() != OK) {
65         ALOGE("FFSource initCheck failed");
66         return -1;
67     }
68
69     return 0;
70 }
71
72 int FFSource::read(unsigned char *buf, size_t size)
73 {
74     ssize_t n = 0;
75
76     n = mSource->readAt(mOffset, buf, size);
77     if (n == UNKNOWN_ERROR) {
78         ALOGE("FFSource readAt failed");
79         return AVERROR(errno);
80     }
81     assert(n >= 0);
82     mOffset += n;
83
84     return n;
85 }
86
87 int64_t FFSource::seek(int64_t pos)
88 {
89     mOffset = pos;
90     return 0;
91 }
92
93 off64_t FFSource::getSize()
94 {
95     off64_t sz = -1;
96
97     if (mSource->getSize(&sz) != OK) {
98          ALOGE("FFSource getSize failed");
99          return AVERROR(errno);
100     }
101
102     return sz;
103 }
104
105 /////////////////////////////////////////////////////////////////
106
107 static int android_open(URLContext *h, const char *url, int flags)
108 {
109     // the url in form of "android-source:<DataSource Ptr>",
110     // the DataSource Pointer passed by the ffmpeg extractor
111     DataSource *source = NULL;
112
113     ALOGD("android source begin open");
114
115     if (!url) {
116         ALOGE("android url is null!");
117         return -1;
118     }
119
120     ALOGD("android open, url: %s", url);
121     sscanf(url + strlen("android-source:"), "%p", &source);
122     if(source == NULL){
123         ALOGE("ffmpeg open data source error!");
124         return -1;
125     }
126     ALOGD("ffmpeg open android data source success, source ptr: %p", source);
127
128     FFSource *ffs = new FFSource(source);
129     h->priv_data = (void *)ffs;
130
131     ALOGD("android source open success");
132
133     return 0;
134 }
135 static int android_read(URLContext *h, unsigned char *buf, int size)
136 {
137     FFSource* ffs = (FFSource *)h->priv_data;
138     return ffs->read(buf, size);
139 }
140
141 static int android_write(URLContext *h, const unsigned char *buf, int size)
142 {
143     return -1;
144 }
145
146 static int64_t android_seek(URLContext *h, int64_t pos, int whence)
147 {
148     FFSource* ffs = (FFSource*)h->priv_data;
149
150     if (whence == AVSEEK_SIZE) {
151         return ffs->getSize();
152     }
153
154     ffs->seek(pos);
155     return 0;
156 }
157
158 static int android_close(URLContext *h)
159 {
160     FFSource* ffs = (FFSource*)h->priv_data;
161     ALOGD("android source close");
162     delete ffs;
163     return 0;
164 }
165
166 static int android_get_handle(URLContext *h)
167 {
168     return (intptr_t)h->priv_data;
169 }
170
171 static int android_check(URLContext *h, int mask)
172 {
173     FFSource* ffs = (FFSource*)h->priv_data;
174
175     if (ffs->init_check() < 0)
176         return AVERROR(EACCES); // FIXME
177
178     return (mask & AVIO_FLAG_READ);
179 }
180
181 static URLProtocol ff_android_protocol;
182
183 void ffmpeg_register_android_source()
184 {
185     memset(&ff_android_protocol, 0, sizeof(URLProtocol));
186     ff_android_protocol.name                = "android-source";
187     ff_android_protocol.url_open            = android_open;
188     ff_android_protocol.url_read            = android_read;
189     ff_android_protocol.url_write           = android_write;
190     ff_android_protocol.url_seek            = android_seek;
191     ff_android_protocol.url_close           = android_close;
192     ff_android_protocol.url_get_file_handle = android_get_handle;
193     ff_android_protocol.url_check           = android_check;
194     
195     ffurl_register_protocol(&ff_android_protocol, sizeof(URLProtocol));
196 }
197
198 }  // namespace android