libstagefright
来源:互联网 发布:c语言输出一个三角形 编辑:程序博客网 时间:2024/06/08 14:26
- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- File List
- Globals
libavcodec/libstagefright.cpp
Go to the documentation of this file.00001 /*00002 * Interface to the Android Stagefright library for00003 * H/W accelerated H.264 decoding00004 *00005 * Copyright (C) 2011 Mohamed Naufal00006 * Copyright (C) 2011 Martin Storsjö00007 *00008 * This file is part of FFmpeg.00009 *00010 * FFmpeg is free software; you can redistribute it and/or00011 * modify it under the terms of the GNU Lesser General Public00012 * License as published by the Free Software Foundation; either00013 * version 2.1 of the License, or (at your option) any later version.00014 *00015 * FFmpeg is distributed in the hope that it will be useful,00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU00018 * Lesser General Public License for more details.00019 *00020 * You should have received a copy of the GNU Lesser General Public00021 * License along with FFmpeg; if not, write to the Free Software00022 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA00023 */00024 00025 #include <binder/ProcessState.h>00026 #include <media/stagefright/MetaData.h>00027 #include <media/stagefright/MediaBufferGroup.h>00028 #include <media/stagefright/MediaDebug.h>00029 #include <media/stagefright/MediaDefs.h>00030 #include <media/stagefright/OMXClient.h>00031 #include <media/stagefright/OMXCodec.h>00032 #include <utils/List.h>00033 #include <new>00034 00035 extern "C" {00036 #include "avcodec.h"00037 #include "libavutil/imgutils.h"00038 }00039 00040 #define OMX_QCOM_COLOR_FormatYVU420SemiPlanar 0x7FA30C0000041 00042 using namespace android;00043 00044 struct Frame {00045 status_t status;00046 size_t size;00047 int64_t time;00048 int key;00049 uint8_t *buffer;00050 MediaBuffer* mbuffer;00051 int32_t w, h;00052 };00053 00054 class CustomSource;00055 00056 struct StagefrightContext {00057 AVCodecContext *avctx;00058 AVBitStreamFilterContext *bsfc;00059 uint8_t* orig_extradata;00060 int orig_extradata_size;00061 sp<MediaSource> *source;00062 List<Frame*> *in_queue, *out_queue;00063 pthread_mutex_t in_mutex, out_mutex;00064 pthread_cond_t condition;00065 pthread_t decode_thread_id;00066 00067 Frame *end_frame;00068 bool source_done;00069 volatile sig_atomic_t thread_started, thread_exited, stop_decode;00070 00071 AVFrame ret_frame;00072 00073 uint8_t *dummy_buf;00074 int dummy_bufsize;00075 00076 OMXClient *client;00077 sp<MediaSource> *decoder;00078 const char *decoder_component;00079 };00080 00081 class CustomSource : public MediaSource {00082 public:00083 CustomSource(AVCodecContext *avctx, sp<MetaData> meta) {00084 s = (StagefrightContext*)avctx->priv_data;00085 source_meta = meta;00086 frame_size = (avctx->width * avctx->height * 3) / 2;00087 buf_group.add_buffer(new MediaBuffer(frame_size));00088 }00089 00090 virtual sp<MetaData> getFormat() {00091 return source_meta;00092 }00093 00094 virtual status_t start(MetaData *params) {00095 return OK;00096 }00097 00098 virtual status_t stop() {00099 return OK;00100 }00101 00102 virtual status_t read(MediaBuffer **buffer,00103 const MediaSource::ReadOptions *options) {00104 Frame *frame;00105 status_t ret;00106 00107 if (s->thread_exited)00108 return ERROR_END_OF_STREAM;00109 pthread_mutex_lock(&s->in_mutex);00110 00111 while (s->in_queue->empty())00112 pthread_cond_wait(&s->condition, &s->in_mutex);00113 00114 frame = *s->in_queue->begin();00115 ret = frame->status;00116 00117 if (ret == OK) {00118 ret = buf_group.acquire_buffer(buffer);00119 if (ret == OK) {00120 memcpy((*buffer)->data(), frame->buffer, frame->size);00121 (*buffer)->set_range(0, frame->size);00122 (*buffer)->meta_data()->clear();00123 (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame,frame->key);00124 (*buffer)->meta_data()->setInt64(kKeyTime, frame->time);00125 } else {00126 av_log(s->avctx, AV_LOG_ERROR, "Failed to acquire MediaBuffer\n");00127 }00128 av_freep(&frame->buffer);00129 }00130 00131 s->in_queue->erase(s->in_queue->begin());00132 pthread_mutex_unlock(&s->in_mutex);00133 00134 av_freep(&frame);00135 return ret;00136 }00137 00138 private:00139 MediaBufferGroup buf_group;00140 sp<MetaData> source_meta;00141 StagefrightContext *s;00142 int frame_size;00143 };00144 00145 void* decode_thread(void *arg)00146 {00147 AVCodecContext *avctx = (AVCodecContext*)arg;00148 StagefrightContext *s = (StagefrightContext*)avctx->priv_data;00149 Frame* frame;00150 MediaBuffer *buffer;00151 int decode_done = 0;00152 do {00153 buffer = NULL;00154 frame = (Frame*)av_mallocz(sizeof(Frame));00155 if (!frame) {00156 frame = s->end_frame;00157 frame->status = AVERROR(ENOMEM);00158 decode_done = 1;00159 s->end_frame = NULL;00160 } else {00161 frame->status = (*s->decoder)->read(&buffer);00162 if (frame->status == OK) {00163 sp<MetaData> outFormat = (*s->decoder)->getFormat();00164 outFormat->findInt32(kKeyWidth , &frame->w);00165 outFormat->findInt32(kKeyHeight, &frame->h);00166 frame->size = buffer->range_length();00167 frame->mbuffer = buffer;00168 } else if (frame->status == INFO_FORMAT_CHANGED) {00169 if (buffer)00170 buffer->release();00171 av_free(frame);00172 continue;00173 } else {00174 decode_done = 1;00175 }00176 }00177 while (true) {00178 pthread_mutex_lock(&s->out_mutex);00179 if (s->out_queue->size() >= 10) {00180 pthread_mutex_unlock(&s->out_mutex);00181 usleep(10000);00182 continue;00183 }00184 break;00185 }00186 s->out_queue->push_back(frame);00187 pthread_mutex_unlock(&s->out_mutex);00188 } while (!decode_done && !s->stop_decode);00189 00190 s->thread_exited = true;00191 00192 return 0;00193 }00194 00195 static av_cold int Stagefright_init(AVCodecContext *avctx)00196 {00197 StagefrightContext *s = (StagefrightContext*)avctx->priv_data;00198 sp<MetaData> meta, outFormat;00199 int32_t colorFormat = 0;00200 int ret;00201 00202 if (!avctx->extradata || !avctx->extradata_size || avctx->extradata[0] != 1)00203 return -1;00204 00205 s->avctx = avctx;00206 s->bsfc = av_bitstream_filter_init("h264_mp4toannexb");00207 if (!s->bsfc) {00208 av_log(avctx, AV_LOG_ERROR, "Cannot open the h264_mp4toannexb BSF!\n");00209 return -1;00210 }00211 00212 s->orig_extradata_size = avctx->extradata_size;00213 s->orig_extradata = (uint8_t*) av_mallocz(avctx->extradata_size +00214 FF_INPUT_BUFFER_PADDING_SIZE);00215 if (!s->orig_extradata) {00216 ret = AVERROR(ENOMEM);00217 goto fail;00218 }00219 memcpy(s->orig_extradata, avctx->extradata, avctx->extradata_size);00220 00221 meta = new MetaData;00222 if (meta == NULL) {00223 ret = AVERROR(ENOMEM);00224 goto fail;00225 }00226 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);00227 meta->setInt32(kKeyWidth, avctx->width);00228 meta->setInt32(kKeyHeight, avctx->height);00229 meta->setData(kKeyAVCC, kTypeAVCC, avctx->extradata, avctx->extradata_size);00230 00231 android::ProcessState::self()->startThreadPool();00232 00233 s->source = new sp<MediaSource>();00234 *s->source = new CustomSource(avctx, meta);00235 s->in_queue = new List<Frame*>;00236 s->out_queue = new List<Frame*>;00237 s->client = new OMXClient;00238 s->end_frame = (Frame*)av_mallocz(sizeof(Frame));00239 if (s->source == NULL || !s->in_queue || !s->out_queue || !s->client ||00240 !s->end_frame) {00241 ret = AVERROR(ENOMEM);00242 goto fail;00243 }00244 00245 if (s->client->connect() != OK) {00246 av_log(avctx, AV_LOG_ERROR, "Cannot connect OMX client\n");00247 ret = -1;00248 goto fail;00249 }00250 00251 s->decoder = new sp<MediaSource>();00252 *s->decoder = OMXCodec::Create(s->client->interface(), meta,00253 false, *s->source, NULL,00254 OMXCodec::kClientNeedsFramebuffer);00255 if ((*s->decoder)->start() != OK) {00256 av_log(avctx, AV_LOG_ERROR, "Cannot start decoder\n");00257 ret = -1;00258 s->client->disconnect();00259 goto fail;00260 }00261 00262 outFormat = (*s->decoder)->getFormat();00263 outFormat->findInt32(kKeyColorFormat, &colorFormat);00264 if (colorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar ||00265 colorFormat == OMX_COLOR_FormatYUV420SemiPlanar)00266 avctx->pix_fmt = PIX_FMT_NV21;00267 else00268 avctx->pix_fmt = PIX_FMT_YUV420P;00269 00270 outFormat->findCString(kKeyDecoderComponent, &s->decoder_component);00271 if (s->decoder_component)00272 s->decoder_component = av_strdup(s->decoder_component);00273 00274 pthread_mutex_init(&s->in_mutex, NULL);00275 pthread_mutex_init(&s->out_mutex, NULL);00276 pthread_cond_init(&s->condition, NULL);00277 return 0;00278 00279 fail:00280 av_bitstream_filter_close(s->bsfc);00281 av_freep(&s->orig_extradata);00282 av_freep(&s->end_frame);00283 delete s->in_queue;00284 delete s->out_queue;00285 delete s->client;00286 return ret;00287 }00288 00289 static int Stagefright_decode_frame(AVCodecContext *avctx, void *data,00290 int *data_size, AVPacket *avpkt)00291 {00292 StagefrightContext *s = (StagefrightContext*)avctx->priv_data;00293 Frame *frame;00294 MediaBuffer *mbuffer;00295 status_t status;00296 size_t size;00297 uint8_t *buf;00298 const uint8_t *src_data[3];00299 int w, h;00300 int src_linesize[3];00301 int orig_size = avpkt->size;00302 AVPacket pkt = *avpkt;00303 int ret;00304 00305 if (!s->thread_started) {00306 pthread_create(&s->decode_thread_id, NULL, &decode_thread, avctx);00307 s->thread_started = true;00308 }00309 00310 if (avpkt && avpkt->data) {00311 av_bitstream_filter_filter(s->bsfc, avctx, NULL, &pkt.data, &pkt.size,00312 avpkt->data, avpkt->size, avpkt->flags & AV_PKT_FLAG_KEY);00313 avpkt = &pkt;00314 }00315 00316 if (!s->source_done) {00317 if(!s->dummy_buf) {00318 s->dummy_buf = (uint8_t*)av_malloc(avpkt->size);00319 if (!s->dummy_buf)00320 return AVERROR(ENOMEM);00321 s->dummy_bufsize = avpkt->size;00322 memcpy(s->dummy_buf, avpkt->data, avpkt->size);00323 }00324 00325 frame = (Frame*)av_mallocz(sizeof(Frame));00326 if (avpkt->data) {00327 frame->status = OK;00328 frame->size = avpkt->size;00329 // Stagefright can't handle negative timestamps -00330 // if needed, work around this by offsetting them manually?00331 if (avpkt->pts >= 0)00332 frame->time = avpkt->pts;00333 frame->key = avpkt->flags & AV_PKT_FLAG_KEY ? 1 : 0;00334 frame->buffer = (uint8_t*)av_malloc(avpkt->size);00335 if (!frame->buffer) {00336 av_freep(&frame);00337 return AVERROR(ENOMEM);00338 }00339 uint8_t *ptr = avpkt->data;00340 // The OMX.SEC decoder fails without this.00341 if (avpkt->size == orig_size + avctx->extradata_size) {00342 ptr += avctx->extradata_size;00343 frame->size = orig_size;00344 }00345 memcpy(frame->buffer, ptr, orig_size);00346 } else {00347 frame->status = ERROR_END_OF_STREAM;00348 s->source_done = true;00349 }00350 00351 while (true) {00352 if (s->thread_exited) {00353 s->source_done = true;00354 break;00355 }00356 pthread_mutex_lock(&s->in_mutex);00357 if (s->in_queue->size() >= 10) {00358 pthread_mutex_unlock(&s->in_mutex);00359 usleep(10000);00360 continue;00361 }00362 s->in_queue->push_back(frame);00363 pthread_cond_signal(&s->condition);00364 pthread_mutex_unlock(&s->in_mutex);00365 break;00366 }00367 }00368 while (true) {00369 pthread_mutex_lock(&s->out_mutex);00370 if (!s->out_queue->empty()) break;00371 pthread_mutex_unlock(&s->out_mutex);00372 if (s->source_done) {00373 usleep(10000);00374 continue;00375 } else {00376 return orig_size;00377 }00378 }00379 00380 frame = *s->out_queue->begin();00381 s->out_queue->erase(s->out_queue->begin());00382 pthread_mutex_unlock(&s->out_mutex);00383 00384 mbuffer = frame->mbuffer;00385 status = frame->status;00386 size = frame->size;00387 w = frame->w;00388 h = frame->h;00389 av_freep(&frame);00390 00391 if (status == ERROR_END_OF_STREAM)00392 return 0;00393 if (status != OK) {00394 if (status == AVERROR(ENOMEM))00395 return status;00396 av_log(avctx, AV_LOG_ERROR, "Decode failed: %x\n", status);00397 return -1;00398 }00399 00400 // The OMX.SEC decoder doesn't signal the modified width/height00401 if (s->decoder_component && !strncmp(s->decoder_component, "OMX.SEC", 7) &&00402 (w & 15 || h & 15)) {00403 if (((w + 15)&~15) * ((h + 15)&~15) * 3/2 == size) {00404 w = (w + 15)&~15;00405 h = (h + 15)&~15;00406 }00407 }00408 00409 if (!avctx->width || !avctx->height || avctx->width > w || avctx->height > h) {00410 avctx->width = w;00411 avctx->height = h;00412 }00413 00414 ret = avctx->reget_buffer(avctx, &s->ret_frame);00415 if (ret < 0) {00416 av_log(avctx, AV_LOG_ERROR, "reget buffer() failed\n");00417 goto end;00418 }00419 00420 src_linesize[0] = w;00421 if (avctx->pix_fmt == PIX_FMT_YUV420P)00422 src_linesize[1] = src_linesize[2] = w/2;00423 else if (avctx->pix_fmt == PIX_FMT_NV21)00424 src_linesize[1] = w;00425 00426 buf = (uint8_t*)mbuffer->data();00427 src_data[0] = buf;00428 src_data[1] = buf + src_linesize[0] * h;00429 src_data[2] = src_data[1] + src_linesize[1] * h/2;00430 av_image_copy(s->ret_frame.data, s->ret_frame.linesize,00431 src_data, src_linesize,00432 avctx->pix_fmt, avctx->width, avctx->height);00433 00434 *data_size = sizeof(AVFrame);00435 *(AVFrame*)data = s->ret_frame;00436 ret = orig_size;00437 end:00438 mbuffer->release();00439 return ret;00440 }00441 00442 static av_cold int Stagefright_close(AVCodecContext *avctx)00443 {00444 StagefrightContext *s = (StagefrightContext*)avctx->priv_data;00445 Frame *frame;00446 00447 if (s->thread_started) {00448 if (!s->thread_exited) {00449 s->stop_decode = 1;00450 00451 // Make sure decode_thread() doesn't get stuck00452 pthread_mutex_lock(&s->out_mutex);00453 while (!s->out_queue->empty()) {00454 frame = *s->out_queue->begin();00455 s->out_queue->erase(s->out_queue->begin());00456 if (frame->size)00457 frame->mbuffer->release();00458 av_freep(&frame);00459 }00460 pthread_mutex_unlock(&s->out_mutex);00461 00462 // Feed a dummy frame prior to signalling EOF.00463 // This is required to terminate the decoder(OMX.SEC)00464 // when only one frame is read during stream info detection.00465 if (s->dummy_buf && (frame = (Frame*)av_mallocz(sizeof(Frame)))) {00466 frame->status = OK;00467 frame->size = s->dummy_bufsize;00468 frame->key = 1;00469 frame->buffer = s->dummy_buf;00470 pthread_mutex_lock(&s->in_mutex);00471 s->in_queue->push_back(frame);00472 pthread_cond_signal(&s->condition);00473 pthread_mutex_unlock(&s->in_mutex);00474 s->dummy_buf = NULL;00475 }00476 00477 pthread_mutex_lock(&s->in_mutex);00478 s->end_frame->status = ERROR_END_OF_STREAM;00479 s->in_queue->push_back(s->end_frame);00480 pthread_cond_signal(&s->condition);00481 pthread_mutex_unlock(&s->in_mutex);00482 s->end_frame = NULL;00483 }00484 00485 pthread_join(s->decode_thread_id, NULL);00486 00487 if (s->ret_frame.data[0])00488 avctx->release_buffer(avctx, &s->ret_frame);00489 00490 s->thread_started = false;00491 }00492 00493 while (!s->in_queue->empty()) {00494 frame = *s->in_queue->begin();00495 s->in_queue->erase(s->in_queue->begin());00496 if (frame->size)00497 av_freep(&frame->buffer);00498 av_freep(&frame);00499 }00500 00501 while (!s->out_queue->empty()) {00502 frame = *s->out_queue->begin();00503 s->out_queue->erase(s->out_queue->begin());00504 if (frame->size)00505 frame->mbuffer->release();00506 av_freep(&frame);00507 }00508 00509 (*s->decoder)->stop();00510 s->client->disconnect();00511 00512 if (s->decoder_component)00513 av_freep(&s->decoder_component);00514 av_freep(&s->dummy_buf);00515 av_freep(&s->end_frame);00516 00517 // Reset the extradata back to the original mp4 format, so that00518 // the next invocation (both when decoding and when called from00519 // av_find_stream_info) get the original mp4 format extradata.00520 av_freep(&avctx->extradata);00521 avctx->extradata = s->orig_extradata;00522 avctx->extradata_size = s->orig_extradata_size;00523 00524 delete s->in_queue;00525 delete s->out_queue;00526 delete s->client;00527 delete s->decoder;00528 delete s->source;00529 00530 pthread_mutex_destroy(&s->in_mutex);00531 pthread_mutex_destroy(&s->out_mutex);00532 pthread_cond_destroy(&s->condition);00533 av_bitstream_filter_close(s->bsfc);00534 return 0;00535 }00536 00537 AVCodec ff_libstagefright_h264_decoder = {00538 "libstagefright_h264",00539 AVMEDIA_TYPE_VIDEO,00540 CODEC_ID_H264,00541 sizeof(StagefrightContext),00542 Stagefright_init,00543 NULL, //encode00544 Stagefright_close,00545 Stagefright_decode_frame,00546 CODEC_CAP_DELAY,00547 NULL, //next00548 NULL, //flush00549 NULL, //supported_framerates00550 NULL, //pixel_formats00551 NULL_IF_CONFIG_SMALL("libstagefright H.264"),00552 };
Generated on Sun Nov 20 19:21:58 2011 for FFmpeg by 1.5.8
l转自http://ffmpeg.org/doxygen/trunk/libstagefright_8cpp-source.html
- libstagefright
- LibStageFright
- libstagefright 音视频同步方案
- libstagefright 音视频同步方案
- FFmpeg中libstagefright.cpp的认识
- 关于libavcodec/libstagefright.cpp的邮件来往
- ndk 8d compiled ffmpeg libstagefright
- libstagefright 编解码格式配置信息导入
- libstagefright openmax编解码数据流向分析
- 编译android 硬解码支持库 libstagefright
- 安卓libStagefright高危漏洞分析
- 安卓libStagefright高危漏洞分析
- 成功编译ffmpeg的android硬解码模块libstagefright
- ffmpeg编译android 硬解码支持库 libstagefright
- xref: /frameworks/av/media/libstagefright/httplive/M3UParser.cpp
- libstagefright 框架设计分析 (1): ALooper, AHandler
- libstagefright 框架设计分析(2): omx 相关
- ffmpeg编译android 硬解码支持库 libstagefright(1)—— git-hub&nb
- 简化Web应用开发 Servlet 3.0特性详解
- ios(iphone/ipad)开发每日一练【2011-11-21】
- Android Codec 集成和 video Overlay
- BS客户端能否同时登陆多个用户
- 如何在64位操作系统里让Revit的命令连接Access数据库?
- libstagefright
- AA065VD数据线连接错位的现象及分析总结
- android Cursor 使用方法
- uva 10300 Ecological Premium
- ubuntu下安装Ice3.4.2
- ListView异步加载图片是非常实用的方法
- git push错误;fatal: The remote end hung up unexpectedly
- rotate的用法
- 智能课程表Android版-日期和时间的动态显示(二)