1 /* 2 * Copyright (C) 2001 Carlos Hasan 3 * Copyright (C) 2001 François Revol 4 * Copyright (C) 2001 Axel Dörfler 5 * Copyright (C) 2004 Marcus Overhagen 6 * Copyright (C) 2009 Stephan Aßmus <superstippi@gmx.de> 7 * 8 * All rights reserved. Distributed under the terms of the MIT License. 9 */ 10 11 //! libavcodec/libavformat based Decoder and Reader plugin for Haiku 12 13 #include "FFmpegPlugin.h" 14 15 #include <stdio.h> 16 17 #include <new> 18 19 #include <Locker.h> 20 21 extern "C" { 22 #include "avcodec.h" 23 #include "avformat.h" 24 } 25 26 #include "AVCodecDecoder.h" 27 #include "AVCodecEncoder.h" 28 #include "AVFormatReader.h" 29 #include "AVFormatWriter.h" 30 #include "CodecTable.h" 31 #include "EncoderTable.h" 32 #include "MuxerTable.h" 33 34 35 //#define TRACE_FFMPEG_PLUGIN 36 #ifdef TRACE_FFMPEG_PLUGIN 37 # define TRACE printf 38 #else 39 # define TRACE(a...) 40 #endif 41 42 #define ERROR(a...) fprintf(stderr, a) 43 44 45 static int 46 manage_locks(void** _lock, enum AVLockOp operation) 47 { 48 TRACE("manage_locks(%p, %d)\n", *_lock, operation); 49 50 BLocker** lock = reinterpret_cast<BLocker**>(_lock); 51 52 switch (operation) { 53 case AV_LOCK_CREATE: 54 TRACE(" AV_LOCK_CREATE\n"); 55 *lock = new(std::nothrow) BLocker("FFmpeg lock"); 56 if (*lock == NULL) 57 return 1; 58 break; 59 60 case AV_LOCK_OBTAIN: 61 TRACE(" AV_LOCK_OBTAIN\n"); 62 if (!(*lock)->Lock()) 63 return 1; 64 break; 65 66 case AV_LOCK_RELEASE: 67 TRACE(" AV_LOCK_RELEASE\n"); 68 (*lock)->Unlock(); 69 break; 70 71 case AV_LOCK_DESTROY: 72 TRACE(" AV_LOCK_DESTROY\n"); 73 delete *lock; 74 break; 75 76 default: 77 return 1; 78 } 79 return 0; 80 } 81 82 83 FFmpegPlugin::GlobalInitilizer::GlobalInitilizer() 84 { 85 if (av_lockmgr_register(manage_locks) != 0) 86 ERROR("Failed to register lock management!\n"); 87 88 av_register_all(); 89 // This will also call av_codec_init() by registering codecs. 90 } 91 92 93 FFmpegPlugin::GlobalInitilizer::~GlobalInitilizer() 94 { 95 av_lockmgr_register(NULL); 96 } 97 98 99 FFmpegPlugin::GlobalInitilizer FFmpegPlugin::sInitilizer; 100 101 102 // #pragma mark - 103 104 105 Decoder* 106 FFmpegPlugin::NewDecoder(uint index) 107 { 108 // TODO: Confirm we can check index here. 109 // if (index == 0) 110 return new(std::nothrow) AVCodecDecoder(); 111 // return NULL; 112 } 113 114 115 Reader* 116 FFmpegPlugin::NewReader() 117 { 118 return new(std::nothrow) AVFormatReader(); 119 } 120 121 122 status_t 123 FFmpegPlugin::GetSupportedFormats(media_format** _formats, size_t* _count) 124 { 125 return build_decoder_formats(_formats, _count); 126 } 127 128 129 Writer* 130 FFmpegPlugin::NewWriter() 131 { 132 return new(std::nothrow) AVFormatWriter(); 133 } 134 135 136 status_t 137 FFmpegPlugin::GetSupportedFileFormats(const media_file_format** _fileFormats, 138 size_t* _count) 139 { 140 *_fileFormats = gMuxerTable; 141 *_count = gMuxerCount; 142 return B_OK; 143 } 144 145 146 Encoder* 147 FFmpegPlugin::NewEncoder(const media_codec_info& codecInfo) 148 { 149 for (size_t i = 0; i < gEncoderCount; i++) { 150 if (codecInfo.sub_id == gEncoderTable[i].codec_info.sub_id) { 151 return new(std::nothrow)AVCodecEncoder(codecInfo.sub_id, 152 gEncoderTable[i].bit_rate_scale); 153 } 154 } 155 return NULL; 156 } 157 158 159 status_t 160 FFmpegPlugin::RegisterNextEncoder(int32* cookie, media_codec_info* _codecInfo, 161 media_format_family* _formatFamily, media_format* _inputFormat, 162 media_format* _outputFormat) 163 { 164 if (*cookie < 0 || *cookie >= (int32)gEncoderCount) 165 return B_BAD_INDEX; 166 167 *_codecInfo = gEncoderTable[*cookie].codec_info; 168 *_formatFamily = gEncoderTable[*cookie].format_family; 169 _inputFormat->type = gEncoderTable[*cookie].input_type; 170 _outputFormat->type = gEncoderTable[*cookie].output_type;; 171 172 *cookie = *cookie + 1; 173 174 return B_OK; 175 } 176 177 178 // #pragma mark - 179 180 181 MediaPlugin* 182 instantiate_plugin() 183 { 184 return new(std::nothrow) FFmpegPlugin; 185 } 186 187