1 /* 2 * Copyright 2010 Stephan Aßmus <superstippi@gmx.de>. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "CodecTable.h" 8 9 extern "C" { 10 #include "avcodec.h" 11 #include "avformat.h" 12 } 13 14 15 #if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) 16 typedef AVCodecID CodecID; 17 #else 18 #define AV_CODEC_ID_NONE CODEC_ID_NONE 19 #define AV_CODEC_ID_PCM_S16LE CODEC_ID_PCM_S16LE 20 #define AV_CODEC_ID_RAWVIDEO CODEC_ID_RAWVIDEO 21 #define AV_CODEC_ID_DVD_SUBTITLE CODEC_ID_DVD_SUBTITLE 22 #define AV_CODEC_ID_ADPCM_IMA_QT CODEC_ID_ADPCM_IMA_QT 23 #endif 24 25 26 //XXX: newer versions have it in libavformat/internal.h 27 typedef struct AVCodecTag { 28 CodecID id; 29 unsigned int tag; 30 } AVCodecTag; 31 32 33 struct AVInputFamily gAVInputFamilies[] = { 34 { B_AIFF_FORMAT_FAMILY, "aiff" }, 35 { B_AVI_FORMAT_FAMILY, "avi" }, 36 { B_MPEG_FORMAT_FAMILY, "mpeg" }, 37 { B_QUICKTIME_FORMAT_FAMILY, "mov" }, 38 { B_ANY_FORMAT_FAMILY, NULL} 39 }; 40 41 static const int32 sMaxFormatCount = 1024; 42 media_format gAVCodecFormats[sMaxFormatCount]; 43 44 45 status_t 46 register_avcodec_tags(media_format_family family, const char *avname, int &index) 47 { 48 AVInputFormat *inputFormat = av_find_input_format(avname); 49 if (inputFormat == NULL) 50 return B_MEDIA_NO_HANDLER; 51 52 BMediaFormats mediaFormats; 53 if (mediaFormats.InitCheck() != B_OK) 54 return B_ERROR; 55 56 for (int tagSet = 0; inputFormat->codec_tag[tagSet]; tagSet++) { 57 const AVCodecTag *tags = inputFormat->codec_tag[tagSet]; 58 if (tags == NULL) 59 continue; 60 61 for (; tags->id != AV_CODEC_ID_NONE; tags++) { 62 // XXX: we might want to keep some strange PCM codecs too... 63 // skip unwanted codec tags 64 if (tags->tag == AV_CODEC_ID_RAWVIDEO 65 || (tags->tag >= AV_CODEC_ID_PCM_S16LE 66 && tags->tag < AV_CODEC_ID_ADPCM_IMA_QT) 67 || tags->tag >= AV_CODEC_ID_DVD_SUBTITLE) 68 continue; 69 70 if (index >= sMaxFormatCount) { 71 fprintf(stderr, "Maximum format count reached for auto-generated " 72 "AVCodec to media_format mapping, but there are still more " 73 "AVCodecs compiled into libavcodec!\n"); 74 break; 75 } 76 77 media_format format; 78 // Determine media type 79 if (tags->tag < AV_CODEC_ID_PCM_S16LE) 80 format.type = B_MEDIA_ENCODED_VIDEO; 81 else 82 format.type = B_MEDIA_ENCODED_AUDIO; 83 84 media_format_description description; 85 memset(&description, 0, sizeof(description)); 86 87 // Hard-code everything to B_MISC_FORMAT_FAMILY to ease matching 88 // later on. 89 description.family = family; 90 switch (family) { 91 case B_AIFF_FORMAT_FAMILY: 92 description.u.aiff.codec = tags->tag; 93 break; 94 case B_AVI_FORMAT_FAMILY: 95 description.u.avi.codec = tags->tag; 96 break; 97 case B_MPEG_FORMAT_FAMILY: 98 description.u.mpeg.id = tags->tag; 99 break; 100 case B_QUICKTIME_FORMAT_FAMILY: 101 description.u.quicktime.codec = tags->tag; 102 break; 103 case B_WAV_FORMAT_FAMILY: 104 description.u.wav.codec = tags->tag; 105 break; 106 default: 107 break; 108 } 109 110 format.require_flags = 0; 111 format.deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS; 112 113 if (mediaFormats.MakeFormatFor(&description, 1, &format) != B_OK) 114 return B_ERROR; 115 116 gAVCodecFormats[index] = format; 117 118 index++; 119 } 120 } 121 return B_OK; 122 } 123 124 125 status_t 126 build_decoder_formats(media_format** _formats, size_t* _count) 127 { 128 BMediaFormats mediaFormats; 129 if (mediaFormats.InitCheck() != B_OK) 130 return B_ERROR; 131 132 int32 index = 0; 133 AVCodec* codec = NULL; 134 while ((codec = av_codec_next(codec)) != NULL) { 135 if (index >= sMaxFormatCount) { 136 fprintf(stderr, "Maximum format count reached for auto-generated " 137 "AVCodec to media_format mapping, but there are still more " 138 "AVCodecs compiled into libavcodec!\n"); 139 break; 140 } 141 media_format format; 142 // Determine media type 143 switch (codec->type) { 144 case AVMEDIA_TYPE_VIDEO: 145 format.type = B_MEDIA_ENCODED_VIDEO; 146 break; 147 case AVMEDIA_TYPE_AUDIO: 148 format.type = B_MEDIA_ENCODED_AUDIO; 149 break; 150 default: 151 // ignore this AVCodec 152 continue; 153 } 154 155 media_format_description description; 156 memset(&description, 0, sizeof(description)); 157 158 // Hard-code everything to B_MISC_FORMAT_FAMILY to ease matching 159 // later on. 160 description.family = B_MISC_FORMAT_FAMILY; 161 description.u.misc.file_format = 'ffmp'; 162 description.u.misc.codec = codec->id; 163 164 format.require_flags = 0; 165 format.deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS; 166 167 if (mediaFormats.MakeFormatFor(&description, 1, &format) != B_OK) 168 return B_ERROR; 169 170 gAVCodecFormats[index] = format; 171 172 index++; 173 } 174 175 *_formats = gAVCodecFormats; 176 *_count = index; 177 178 return B_OK; 179 } 180 181