codecfinder.py 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# Transmageddon
# Copyright (C) 2009 Christian Schaller <uraeus@gnome.org>
# Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
# 
# Some code in this file came originally from the encode.py file in Pitivi
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
18
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
19

20 21 22
# THIS CODE CAN PROBABLY BE REDUCED A LOT IN SIZE SINCE ITS 3 BIG FUNCTIONS
# DOING ESSENTIALLY THE SAME, ESPECIALLY NOW THAT THE ONLY SPECIAL CASING
# REMAINING IS FFMUXERS AND WAVPACK
23 24


25 26 27
from gi.repository import Gst
from gi.repository import GstPbutils
#Gst.init(None)
28 29 30 31 32 33 34

def list_compat(a1, b1):
   for x1 in a1:
       if not x1 in b1:
           return False
   return True

35 36 37 38 39 40 41
containermap = { 'Ogg' : "application/ogg", \
        'Matroska' : "video/x-matroska", \
        'MXF' : "application/mxf", \
        'AVI' : "video/x-msvideo", \
        'Quicktime' : "video/quicktime,variant=apple", \
        'MPEG4' : "video/quicktime,variant=iso", \
        'MPEG PS' : "video/mpeg,mpegversion=2,systemstream=true", \
42 43
        'MPEG TS' : "video/mpegts,systemstream=true,packetsize=188", \
        'AVCHD/BD' : "video/mpegts,systemstream=true,packetsize=192",\
44 45
        'FLV' : "video/x-flv", \
        '3GPP' : "video/quicktime,variant=3gpp", \
46
        'ASF' : "video/x-ms-asf, parsed=true", \
47 48 49 50 51 52 53 54 55 56 57
        'WebM' : "video/webm", \
        'No container' : False }

csuffixmap =   { 'Ogg' : ".ogg", \
        'Matroska' : ".mkv", \
        'MXF' : ".mxf", \
        'AVI' : ".avi", \
        'Quicktime' : ".mov", \
        'MPEG4' : ".mp4", \
        'MPEG PS' : ".mpg", \
        'MPEG TS' : ".ts", \
58
        'AVCHD/BD' : ".m2ts", \
59 60 61
        'FLV' : ".flv", \
        '3GPP' : ".3gp",
        'ASF' : ".asf", \
62 63
        'WebM' : ".webm", \
        'No container' : ".null" }
64 65 66 67 68 69 70 71 72 73 74 75

audiosuffixmap =   { 'Ogg' : ".ogg", \
        'Matroska' : ".mkv", \
        'MXF' : ".mxf", \
        'AVI' : ".avi", \
        'Quicktime' : ".m4a",
        'MPEG4' : ".mp4", \
        'MPEG PS' : ".mpg", \
        'MPEG TS' : ".ts", \
        'FLV' : ".flv", \
        '3GPP' : ".3gp", \
        'ASF' : ".wma", \
76 77
        'WebM' : ".webm", \
        'Opus' : ".opus" }
78 79 80 81 82

nocontainersuffixmap = {
         'audio/mpeg, mpegversion=(int)1, layer=(int)3' : ".mp3", \
         'audio/mpeg, mpegversion=(int)4, stream-format=(string)adts' : ".aac", \
         'audio/x-flac' : ".flac" }
83 84 85 86 87 88 89 90 91 92 93 94 95 96

codecmap = { 'Vorbis' : "audio/x-vorbis", \
        'FLAC' : "audio/x-flac", \
        'mp3' : "audio/mpeg, mpegversion=(int)1, layer=(int)3", \
        'AAC' : "audio/mpeg,mpegversion=4", \
        'AC3' : "audio/x-ac3", \
        'Speex' : "audio/x-speex",
        'Celt Ultra' : "audio/x-celt", \
        'ALAC' : "audio/x-alac", \
        'Windows Media Audio 2' : "audio/x-wma, wmaversion=(int)2", \
        'Theora' : "video/x-theora", \
        'Dirac' : "video/x-dirac", \
        'H264' : "video/x-h264", \
        'MPEG2' : "video/mpeg,mpegversion=2,systemstream=false", \
97
        'MPEG4' : "video/mpeg,mpegversion=4,systemstream=false", \
98 99 100 101 102 103
        'Windows Media Video 2' : "video/x-wmv,wmvversion=2", \
        'dnxhd' : "video/x-dnxhd", \
        'divx5' : "video/x-divx,divxversion=5", \
        'divx4' : "video/x-divx,divxversion=4", \
        'AMR-NB' : "audio/AMR", \
        'H263+' : "video/x-h263,variant=itu,h263version=h263p", \
104
        'On2 vp8' : "video/x-vp8", \
105
        'On2 vp9' : "video/x-vp9", \
106
        'mp2' : "audio/mpeg,mpegversion=(int)1, layer=(int)2", \
107
        'MPEG1' : "video/mpeg,mpegversion=(int)1,systemstream=false", \
108 109
        'Opus'  :  "audio/x-opus", \
        'xvid'  :   "video/mpeg,mpegversion=4,systemstream=false,profile=advanced-simple" }
110

111 112 113 114
#####
#This code checks for available muxers and return a unique caps string
#for each. It also creates a python dictionary mapping the caps strings 
#to concrete element names. 
115 116 117

# This part of the file might be mostly uneeded due to the encodebin port, seems remaining code 
# calling it could be removed even if its a biggish effort
118
#####
Łukasz Jernaś's avatar
Łukasz Jernaś committed
119

120 121 122 123 124
def get_muxer_element(containercaps): 
   """
   Check all muxers for their caps and create a dictionary mapping caps 
   to element names. Then return elementname
   """
125
   flist = Gst.Registry.get().get_feature_list(Gst.ElementFactory)
126 127
   muxers = []
   features = []
128
   elementname = False
129
   for fact in flist:
130 131 132
       # This code is a lot simpler than what I used with 0.10 thanks to the list_is_type call.
       # 16 is the 'muxer' class of plugins
       if Gst.ElementFactory.list_is_type(fact, 16):
133 134
           muxers.append(fact.get_name())
           features.append(fact)
135
   muxerfeature = dict(list(zip(muxers, features)))
136 137
   for muxer in muxers:
           element = muxer
138
           factory = Gst.Registry.get().lookup_feature(str(muxer))
139
           sinkcaps = [x.get_caps() for x in factory.get_static_pad_templates() \
140
                   if x.direction == Gst.PadDirection.SRC]
141
           for caps in sinkcaps:
142
               intersect = caps.intersect(containercaps)
143
               if intersect.to_string() != "EMPTY":
144 145 146
                   if elementname == False:
                       elementname = element
                   else:
147 148
                       mostrecent = Gst.PluginFeature.get_rank(muxerfeature[element])
                       original = Gst.PluginFeature.get_rank(muxerfeature[elementname])
149 150
                       if mostrecent >= original:
                           elementname = element
151 152
   # This is just a test of if an element exist that can mux this format now, 
   # so elementname doesn't really matter any more.
153 154 155
   return elementname

######
156 157 158 159
#   This code checks for available audio encoders and return a unique caps
#   string for each.
#   It also creates a python dictionary mapping the caps strings to concrete
#   element names.
Łukasz Jernaś's avatar
Łukasz Jernaś committed
160
#####
161 162 163
def get_audio_encoder_element(audioencodercaps):
   """
   Check all audio encoders for their caps and create a dictionary 
164 165 166 167
   mapping caps to element names, only using the highest ranked element
   for each unique caps value. The input of the function is the unique caps
   and it returns the elementname. If the caps to not exist in dictionary it
   will return False.
168
   """
169

170
   flist = Gst.Registry.get().get_feature_list(Gst.ElementFactory)
171 172
   encoders = []
   features = []
173
   elementname = False
174
   for fact in flist:
175 176 177
      if Gst.ElementFactory.list_is_type(fact, 2):
           test=fact.get_name()
           # print "audioencoder is " + str(test)
178 179
           # excluding wavpackenc as the fact that it got two SRC pads mess up
           # the logic of this code
180
           if fact.get_name() != 'wavpackenc':
181 182 183
               if fact.get_name() != 'encodebin':
                   encoders.append(fact.get_name())
                   features.append(fact)
184
   encoderfeature = dict(list(zip(encoders, features)))
185 186 187 188 189
   
   if isinstance(audioencodercaps, str): # this value should always be a caps value, so this sometimes being a string is a bug
       incomingcaps = Gst.caps_from_string(audioencodercaps)
   else:
       incomingcaps = audioencodercaps
190
   for x in encoders:
191
           element = x
192
           factory = Gst.Registry.get().lookup_feature(str(x))
193
           sinkcaps = [x.get_caps() for x in factory.get_static_pad_templates() \
194
                   if x.direction == Gst.PadDirection.SRC]
195
           for caps in sinkcaps:
196 197 198
               # print "incomingcaps is " +str(incomingcaps)
               intersect= caps.intersect(incomingcaps).to_string()
               if intersect != "EMPTY":
199 200 201
                   if elementname == False:
                       elementname = element
                   else:
202 203
                       mostrecent = Gst.PluginFeature.get_rank(encoderfeature[element])
                       original = Gst.PluginFeature.get_rank(encoderfeature[elementname])
204 205
                       if mostrecent >= original:
                           elementname = element
206 207 208
   return elementname

#######
209
# This code checks for available video encoders and return a unique caps
210
# string for each. It also creates a python dictionary mapping the caps 
Łukasz Jernaś's avatar
Łukasz Jernaś committed
211
# strings to concrete element names.
212
#######
Łukasz Jernaś's avatar
Łukasz Jernaś committed
213

214 215 216
def get_video_encoder_element(videoencodercaps):
   """
   Check all video encoders for their caps and create a dictionary 
217 218 219 220
   mapping caps to element names, only using the highest ranked element
   for each unique caps value. The input of the function is the unique caps
   and it returns the elementname. If the caps to not exist in dictionary it
   will return False.
221
   """
222

223
   flist = Gst.Registry.get().get_feature_list(Gst.ElementFactory)
224 225
   encoders = []
   features = []
226
   elementname = False
227
   for fact in flist:
228 229 230
       if Gst.ElementFactory.list_is_type(fact, 2814749767106562):
           test=fact.get_name()
           # print "videoencoder is " + str(test)
231 232
           encoders.append(fact.get_name())
           features.append(fact) 
233 234 235 236
       # elif list_compat(["Codec", "Encoder", "Image"], \
       #        fact.get_metadata().split('/')):
       #    encoders.append(fact.get_name())
       #   features.append(fact)
237
   encoderfeature = dict(list(zip(encoders, features)))
238
   # print "videoencodercaps is " + str(videoencodercaps)
239
   incomingcaps = videoencodercaps
240
   for x in encoders:
241
           element = x
242
           factory = Gst.Registry.get().lookup_feature(str(x))
243
           sinkcaps = [x.get_caps() for x in factory.get_static_pad_templates() \
244
                   if x.direction == Gst.PadDirection.SRC]
245
           for caps in sinkcaps:
246 247
               intersect= caps.intersect(incomingcaps).to_string()
               if intersect != "EMPTY":
248 249 250
                   if elementname == False:
                       elementname = element
                   else:
251 252
                       mostrecent = Gst.PluginFeature.get_rank(encoderfeature[element])
                       original = Gst.PluginFeature.get_rank(encoderfeature[elementname])
253 254
                       if mostrecent >= original:
                           elementname = element
255
   return elementname