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 #if LIBAVCODEC_VERSION_INT >= ((57 << 16) | (0 << 8)) 91 avfilter_register_all(); 92 #endif 93 } 94 95 96 FFmpegPlugin::GlobalInitilizer::~GlobalInitilizer() 97 { 98 av_lockmgr_register(NULL); 99 } 100 101 102 FFmpegPlugin::GlobalInitilizer FFmpegPlugin::sInitilizer; 103 104 105 // #pragma mark - 106 107 108 Decoder* 109 FFmpegPlugin::NewDecoder(uint index) 110 { 111 // TODO: Confirm we can check index here. 112 // if (index == 0) 113 return new(std::nothrow) AVCodecDecoder(); 114 // return NULL; 115 } 116 117 118 Reader* 119 FFmpegPlugin::NewReader() 120 { 121 return new(std::nothrow) AVFormatReader(); 122 } 123 124 125 status_t 126 FFmpegPlugin::GetSupportedFormats(media_format** _formats, size_t* _count) 127 { 128 return build_decoder_formats(_formats, _count); 129 } 130 131 132 Writer* 133 FFmpegPlugin::NewWriter() 134 { 135 return new(std::nothrow) AVFormatWriter(); 136 } 137 138 139 status_t 140 FFmpegPlugin::GetSupportedFileFormats(const media_file_format** _fileFormats, 141 size_t* _count) 142 { 143 *_fileFormats = gMuxerTable; 144 *_count = gMuxerCount; 145 return B_OK; 146 } 147 148 149 Encoder* 150 FFmpegPlugin::NewEncoder(const media_codec_info& codecInfo) 151 { 152 for (size_t i = 0; i < gEncoderCount; i++) { 153 if (codecInfo.sub_id == gEncoderTable[i].codec_info.sub_id) { 154 return new(std::nothrow)AVCodecEncoder(codecInfo.sub_id, 155 gEncoderTable[i].bit_rate_scale); 156 } 157 } 158 return NULL; 159 } 160 161 162 Encoder* 163 FFmpegPlugin::NewEncoder(const media_format& format) 164 { 165 for (size_t i = 0; i < gEncoderCount; i++) { 166 if (format.type == gEncoderTable[i].output_type) { 167 return new(std::nothrow)AVCodecEncoder( 168 gEncoderTable[i].codec_info.sub_id, 169 gEncoderTable[i].bit_rate_scale); 170 } 171 } 172 return NULL; 173 } 174 175 176 status_t 177 FFmpegPlugin::RegisterNextEncoder(int32* cookie, media_codec_info* _codecInfo, 178 media_format_family* _formatFamily, media_format* _inputFormat, 179 media_format* _outputFormat) 180 { 181 if (*cookie < 0 || *cookie >= (int32)gEncoderCount) 182 return B_BAD_INDEX; 183 184 *_codecInfo = gEncoderTable[*cookie].codec_info; 185 *_formatFamily = gEncoderTable[*cookie].format_family; 186 _inputFormat->type = gEncoderTable[*cookie].input_type; 187 _outputFormat->type = gEncoderTable[*cookie].output_type;; 188 189 *cookie = *cookie + 1; 190 191 return B_OK; 192 } 193 194 195 // #pragma mark - 196 197 198 MediaPlugin* 199 instantiate_plugin() 200 { 201 return new(std::nothrow) FFmpegPlugin; 202 } 203 204