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 "avformat.h" 23 } 24 25 #include "AVCodecDecoder.h" 26 #include "AVCodecEncoder.h" 27 #include "AVFormatReader.h" 28 #include "AVFormatWriter.h" 29 #include "CodecTable.h" 30 #include "EncoderTable.h" 31 #include "MuxerTable.h" 32 33 34 //#define TRACE_FFMPEG_PLUGIN 35 #ifdef TRACE_FFMPEG_PLUGIN 36 # define TRACE printf 37 #else 38 # define TRACE(a...) 39 #endif 40 41 #define ERROR(a...) fprintf(stderr, a) 42 43 44 static int 45 manage_locks(void** _lock, enum AVLockOp operation) 46 { 47 TRACE("manage_locks(%p, %d)\n", *_lock, operation); 48 49 BLocker** lock = reinterpret_cast<BLocker**>(_lock); 50 51 switch (operation) { 52 case AV_LOCK_CREATE: 53 TRACE(" AV_LOCK_CREATE\n"); 54 *lock = new(std::nothrow) BLocker("FFmpeg lock"); 55 if (*lock == NULL) 56 return 1; 57 break; 58 59 case AV_LOCK_OBTAIN: 60 TRACE(" AV_LOCK_OBTAIN\n"); 61 if (!(*lock)->Lock()) 62 return 1; 63 break; 64 65 case AV_LOCK_RELEASE: 66 TRACE(" AV_LOCK_RELEASE\n"); 67 (*lock)->Unlock(); 68 break; 69 70 case AV_LOCK_DESTROY: 71 TRACE(" AV_LOCK_DESTROY\n"); 72 delete *lock; 73 break; 74 75 default: 76 return 1; 77 } 78 return 0; 79 } 80 81 82 FFmpegPlugin::GlobalInitilizer::GlobalInitilizer() 83 { 84 if (av_lockmgr_register(manage_locks) != 0) 85 ERROR("Failed to register lock management!\n"); 86 87 av_register_all(); 88 // This will also call av_codec_init() by registering codecs. 89 } 90 91 92 FFmpegPlugin::GlobalInitilizer::~GlobalInitilizer() 93 { 94 av_lockmgr_register(NULL); 95 } 96 97 98 FFmpegPlugin::GlobalInitilizer FFmpegPlugin::sInitilizer; 99 100 101 // #pragma mark - 102 103 104 Decoder* 105 FFmpegPlugin::NewDecoder(uint index) 106 { 107 // TODO: Confirm we can check index here. 108 // if (index == 0) 109 return new(std::nothrow) AVCodecDecoder(); 110 // return NULL; 111 } 112 113 114 Reader* 115 FFmpegPlugin::NewReader() 116 { 117 return new(std::nothrow) AVFormatReader(); 118 } 119 120 121 status_t 122 FFmpegPlugin::GetSupportedFormats(media_format** _formats, size_t* _count) 123 { 124 BMediaFormats mediaFormats; 125 if (mediaFormats.InitCheck() != B_OK) 126 return B_ERROR; 127 128 for (int i = 0; i < gCodecCount; i++) { 129 media_format_description description; 130 description.family = gCodecTable[i].family; 131 switch(description.family) { 132 case B_WAV_FORMAT_FAMILY: 133 description.u.wav.codec = gCodecTable[i].fourcc; 134 break; 135 case B_AIFF_FORMAT_FAMILY: 136 description.u.aiff.codec = gCodecTable[i].fourcc; 137 break; 138 case B_AVI_FORMAT_FAMILY: 139 description.u.avi.codec = gCodecTable[i].fourcc; 140 break; 141 case B_MPEG_FORMAT_FAMILY: 142 description.u.mpeg.id = gCodecTable[i].fourcc; 143 break; 144 case B_QUICKTIME_FORMAT_FAMILY: 145 description.u.quicktime.codec = gCodecTable[i].fourcc; 146 break; 147 case B_MISC_FORMAT_FAMILY: 148 description.u.misc.file_format = 149 (uint32)(gCodecTable[i].fourcc >> 32); 150 description.u.misc.codec = (uint32) gCodecTable[i].fourcc; 151 break; 152 default: 153 break; 154 } 155 media_format format; 156 format.type = gCodecTable[i].type; 157 format.require_flags = 0; 158 format.deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS; 159 if (mediaFormats.MakeFormatFor(&description, 1, &format) != B_OK) 160 return B_ERROR; 161 gAVCodecFormats[i] = format; 162 } 163 164 *_formats = gAVCodecFormats; 165 *_count = gCodecCount; 166 return B_OK; 167 } 168 169 170 Writer* 171 FFmpegPlugin::NewWriter() 172 { 173 return new(std::nothrow) AVFormatWriter(); 174 } 175 176 177 status_t 178 FFmpegPlugin::GetSupportedFileFormats(const media_file_format** _fileFormats, 179 size_t* _count) 180 { 181 *_fileFormats = gMuxerTable; 182 *_count = gMuxerCount; 183 return B_OK; 184 } 185 186 187 Encoder* 188 FFmpegPlugin::NewEncoder(const media_codec_info& codecInfo) 189 { 190 for (size_t i = 0; i < gEncoderCount; i++) { 191 if (codecInfo.sub_id == gEncoderTable[i].codec_info.sub_id) { 192 return new(std::nothrow)AVCodecEncoder(codecInfo.sub_id, 193 gEncoderTable[i].bit_rate_scale); 194 } 195 } 196 return NULL; 197 } 198 199 200 status_t 201 FFmpegPlugin::RegisterNextEncoder(int32* cookie, media_codec_info* _codecInfo, 202 media_format_family* _formatFamily, media_format* _inputFormat, 203 media_format* _outputFormat) 204 { 205 if (*cookie < 0 || *cookie >= (int32)gEncoderCount) 206 return B_BAD_INDEX; 207 208 *_codecInfo = gEncoderTable[*cookie].codec_info; 209 *_formatFamily = gEncoderTable[*cookie].format_family; 210 _inputFormat->type = gEncoderTable[*cookie].input_type; 211 _outputFormat->type = gEncoderTable[*cookie].output_type;; 212 213 *cookie = *cookie + 1; 214 215 return B_OK; 216 } 217 218 219 // #pragma mark - 220 221 222 MediaPlugin* 223 instantiate_plugin() 224 { 225 return new(std::nothrow) FFmpegPlugin; 226 } 227 228