Permalink
Browse files

Merge branch 'fixes/0.24' of github.com:MythTV/mythtv into fixes/0.24

  • Loading branch information...
2 parents 9f9dcf5 + 07b1cc1 commit f5fd11fa54141cab0239f15947faa3a41a2e9cef @stuarta stuarta committed Nov 16, 2011
Showing with 2,723 additions and 2,125 deletions.
  1. BIN mythplugins/mytharchive/i18n/mytharchive_da.qm
  2. +11 −9 mythplugins/mytharchive/i18n/mytharchive_da.ts
  3. BIN mythplugins/mythgallery/i18n/mythgallery_da.qm
  4. +48 −38 mythplugins/mythgallery/i18n/mythgallery_da.ts
  5. +12 −10 mythtv/bindings/python/MythTV/system.py
  6. +63 −23 mythtv/bindings/python/MythTV/tmdb/tmdb_api.py
  7. +1 −1 mythtv/configure
  8. +16 −0 mythtv/contrib/imports/mirobridge/mirobridge/mirobridge_interpreter_4_0_2.py
  9. +0 −1 mythtv/external/FFmpeg/libavcodec/Makefile
  10. +25 −11 mythtv/external/FFmpeg/libavcodec/aac.h
  11. +644 −178 mythtv/external/FFmpeg/libavcodec/aacdec.c
  12. +8 −0 mythtv/external/FFmpeg/libavcodec/aacdectab.h
  13. +16 −22 mythtv/external/FFmpeg/libavcodec/aacsbr.c
  14. BIN mythtv/i18n/mythfrontend_da.qm
  15. +1,717 −1,728 mythtv/i18n/mythfrontend_da.ts
  16. +7 −7 mythtv/libs/libmyth/audiooutput.cpp
  17. +15 −11 mythtv/libs/libmyth/audiooutputalsa.cpp
  18. +17 −16 mythtv/libs/libmyth/audiooutputbase.cpp
  19. +5 −4 mythtv/libs/libmyth/audiooutputbase.h
  20. +7 −8 mythtv/libs/libmyth/audiooutputjack.cpp
  21. +2 −0 mythtv/libs/libmyth/audiooutputsettings.cpp
  22. +2 −2 mythtv/libs/libmyth/libmyth.pro
  23. +6 −4 mythtv/libs/libmythdvdnav/dvdread/dvd_udf.c
  24. +7 −0 mythtv/libs/libmythdvdnav/dvdread/ifo_read.c
  25. +2 −2 mythtv/libs/libmythtv/DVDRingBuffer.cpp
  26. +4 −2 mythtv/libs/libmythtv/avformatdecoder.cpp
  27. +2 −2 mythtv/libs/libmythtv/decoderbase.cpp
  28. +28 −11 mythtv/libs/libmythtv/mythplayer.cpp
  29. +4 −0 mythtv/libs/libmythtv/mythplayer.h
  30. +21 −17 mythtv/libs/libmythtv/osd.h
  31. +1 −0 mythtv/libs/libmythui/mythrender_opengl.cpp
  32. +4 −3 mythtv/programs/mythcommflag/PrePostRollFlagger.cpp
  33. +1 −1 mythtv/programs/mythfrontend/networkcontrol.cpp
  34. +27 −14 mythtv/programs/mythtranscode/transcode.cpp
  35. 0 mythtv/themes/default/keyboard/{dk.xml → da.xml}
  36. 0 mythtv/themes/default/keyboard/{dk_ui.xml → da_ui.xml}
View
BIN mythplugins/mytharchive/i18n/mytharchive_da.qm
Binary file not shown.
View
20 mythplugins/mytharchive/i18n/mytharchive_da.ts
@@ -164,12 +164,12 @@
<message>
<location filename="../mytharchive/mythburn.cpp" line="400"/>
<source>Retrieving File Information. Please Wait...</source>
- <translation>Modtager information.for fil Vent venligst...</translation>
+ <translation>Modtager information for fil. Vent venligst...</translation>
</message>
<message>
<location filename="../mytharchive/mythburn.cpp" line="466"/>
<source>Encoder: </source>
- <translation>Encoder:</translation>
+ <translation>Encoder: </translation>
</message>
<message>
<location filename="../mytharchive/mythburn.cpp" line="792"/>
@@ -237,7 +237,7 @@
<message>
<location filename="../mytharchive/main.cpp" line="304"/>
<source>View Archive Log</source>
- <translation>Vis arkiv log</translation>
+ <translation>Vis arkivlog</translation>
</message>
<message>
<location filename="../mytharchive/main.cpp" line="306"/>
@@ -657,6 +657,13 @@ Indsæt en blank DVD i drevet og vælg en af mulighederne nedenfor.</translation
<context>
<name>RecordingSelector</name>
<message>
+ <location filename="../mytharchive/recordingselector.cpp" line="119"/>
+ <source>Retrieving Recording List.
+Please Wait...</source>
+ <translation>Modtager optagelseslisten.
+Vent venligst...</translation>
+ </message>
+ <message>
<location filename="../mytharchive/recordingselector.cpp" line="199"/>
<source>Clear All</source>
<translation>Slet alt</translation>
@@ -679,11 +686,6 @@ Indsæt en blank DVD i drevet og vælg en af mulighederne nedenfor.</translation
<translation>Alle optagelser</translation>
</message>
<message>
- <location filename="../mytharchive/recordingselector.cpp" line="119"/>
- <source>Retrieving Recording List. Please Wait...</source>
- <translation>Modtager optagelseslisten. Vent venligst...</translation>
- </message>
- <message>
<location filename="../mytharchive/recordingselector.cpp" line="143"/>
<source>Either you don&apos;t have any recordings or no recordings are available locally!</source>
<translation>Enten har du ikke nogen optagelser eller også er de ikke lokalt tilgængelige!</translation>
@@ -873,7 +875,7 @@ Indsæt en blank DVD i drevet og vælg en af mulighederne nedenfor.</translation
<message>
<location filename="themestrings.h" line="53"/>
<source>Select Archive Items</source>
- <translation>Vælg arkiv emner</translation>
+ <translation>Vælg arkivemner</translation>
</message>
<message>
<location filename="themestrings.h" line="55"/>
View
BIN mythplugins/mythgallery/i18n/mythgallery_da.qm
Binary file not shown.
View
86 mythplugins/mythgallery/i18n/mythgallery_da.ts
@@ -216,112 +216,112 @@
<context>
<name>MythControls</name>
<message>
- <location filename="../mythgallery/main.cpp" line="69"/>
+ <location filename="../mythgallery/main.cpp" line="71"/>
<source>Image viewer / slideshow</source>
<translation>Billedviser / slideshow</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="72"/>
+ <location filename="../mythgallery/main.cpp" line="74"/>
<source>Start/Stop Slideshow</source>
<translation>Start/stop slideshow</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="74"/>
+ <location filename="../mythgallery/main.cpp" line="76"/>
<source>Go to the first image in thumbnail view</source>
<translation>Gå til det første billede i oversigtsvisning</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="76"/>
+ <location filename="../mythgallery/main.cpp" line="78"/>
<source>Go to the last image in thumbnail view</source>
<translation>Gå til det sidste billede i oversigtsvisning</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="78"/>
+ <location filename="../mythgallery/main.cpp" line="80"/>
<source>Start Slideshow in thumbnail view</source>
<translation>Start slideshow i oversigtsvisning</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="80"/>
+ <location filename="../mythgallery/main.cpp" line="82"/>
<source>Start Random Slideshow in thumbnail view</source>
<translation>Start tilfældigt slideshow i oversigtsvisning</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="83"/>
+ <location filename="../mythgallery/main.cpp" line="85"/>
<source>Rotate image right 90 degrees</source>
<translation>Roter billede 90 grader mod højre</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="85"/>
+ <location filename="../mythgallery/main.cpp" line="87"/>
<source>Rotate image left 90 degrees</source>
<translation>Roter billede 90 grader mod venstre</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="87"/>
+ <location filename="../mythgallery/main.cpp" line="89"/>
<source>Zoom image out</source>
<translation>Zoom ud</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="89"/>
+ <location filename="../mythgallery/main.cpp" line="91"/>
<source>Zoom image in</source>
<translation>Zoom ind</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="91"/>
+ <location filename="../mythgallery/main.cpp" line="93"/>
<source>Scroll image up</source>
<translation>Flyt billede op</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="93"/>
+ <location filename="../mythgallery/main.cpp" line="95"/>
<source>Scroll image left</source>
<translation>Flyt billede til venstre</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="95"/>
+ <location filename="../mythgallery/main.cpp" line="97"/>
<source>Scroll image right</source>
<translation>Flyt billede til venstre</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="97"/>
+ <location filename="../mythgallery/main.cpp" line="99"/>
<source>Scroll image down</source>
<translation>Flyt billede ned</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="99"/>
+ <location filename="../mythgallery/main.cpp" line="101"/>
<source>Recenter image</source>
<translation>Centrer billedet</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="101"/>
+ <location filename="../mythgallery/main.cpp" line="103"/>
<source>Full-size (un-zoom) image</source>
<translation>Vis billede i fuld størrelse</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="103"/>
+ <location filename="../mythgallery/main.cpp" line="105"/>
<source>Go to the upper-left corner of the image</source>
<translation>Gå til øverste venstre hjørne af billedet</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="105"/>
+ <location filename="../mythgallery/main.cpp" line="107"/>
<source>Go to the lower-right corner of the image</source>
<translation>Gå til nederste højre hjørne af billedet</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="107"/>
+ <location filename="../mythgallery/main.cpp" line="109"/>
<source>Mark image</source>
<translation>Marker billede</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="109"/>
+ <location filename="../mythgallery/main.cpp" line="111"/>
<source>Toggle scale to fullscreen/scale to fit</source>
<translation>Skift mellem skaler-til-fuldskærm og skaler-for-tilpasning</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="111"/>
+ <location filename="../mythgallery/main.cpp" line="113"/>
<source>MythGallery Media Handler 1/2</source>
<translation>MythGallery mediehåndtering 1/2</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="114"/>
+ <location filename="../mythgallery/main.cpp" line="116"/>
<source>MythGallery Media Handler 2/2</source>
<translation>MythGallery mediehåndtering 2/2</translation>
</message>
@@ -344,17 +344,27 @@
<translation>Stier hvor der skal importeres billeder fra</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="127"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="84"/>
+ <source>Automatically load MythGallery to display pictures</source>
+ <translation>Start automatisk MythGallery for at vise billeder</translation>
+ </message>
+ <message>
+ <location filename="../mythgallery/gallerysettings.cpp" line="86"/>
+ <source>When a new CD-Rom or removable storage device containing pictures is detected then load MythGallery to display the content.</source>
+ <translation>Når der detekteres en ny CD-ROM eller flytbar disk indeholdende billeder, startes MythGallery for at vise indholdet.</translation>
+ </message>
+ <message>
+ <location filename="../mythgallery/gallerysettings.cpp" line="136"/>
<source>Type of transition</source>
<translation>Overgangstype</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="150"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="159"/>
<source>Type of background</source>
<translation>Baggrundstype</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="165"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="174"/>
<source>This is the number of seconds to display each picture.</source>
<translation>Antal sekunder som hvert billede skal vises.</translation>
</message>
@@ -364,37 +374,37 @@
<translation>Dette er en kolon separeret liste af stier. Hvis stien i listen er en mappe, bliver indeholdet kopieret. Hvis det er en kommando, bliver den kørt.</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="142"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="151"/>
<source>This is the type of transition used between pictures in slideshow mode.</source>
<translation>Dette er den overgangstype der benyttes mellem billederne under slideshow.</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="155"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="164"/>
<source>This is the type of background for each picture in single view mode.</source>
<translation>Dette er den baggrundstype der benyttes til hvert billede under enkeltbilledvisning.</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="163"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="172"/>
<source>Slideshow Delay</source>
<translation>Slideshow pause</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="86"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="95"/>
<source>Use OpenGL transitions</source>
<translation>Brug OpenGL overgange</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="88"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="97"/>
<source>Check this to enable OpenGL based slideshow transitions</source>
<translation>Sæt denne for at aktivere OpenGL overgange</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="96"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="105"/>
<source>Type of OpenGL transition</source>
<translation>OpenGL overgangstype</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="108"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="117"/>
<source>This is the type of OpenGL transition used between pictures in slideshow mode.</source>
<translation>Dette er den OpenGL overgangetype som benyttes mellem billeder i slideshow mode.</translation>
</message>
@@ -419,12 +429,12 @@
<translation>Hvis aktiv, bliver mini-billederne gemt i&apos;.thumbcache&apos; mapper i ovenstående mappe. Ellers bliver de gemt i brugerens hjemmemappe.</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="173"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="182"/>
<source>Recurse into directories</source>
<translation>Inkluder undermapper</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="174"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="183"/>
<source>Check this to let the slideshow recurse into sub-directories.</source>
<translation>Sættes hvis slideshowet skal indeholde billeder fra undermapper.</translation>
</message>
@@ -449,22 +459,22 @@
<translation>Sorteringsorden af mini-billeder under navigering.</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="117"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="126"/>
<source>Duration of OpenGL Transition (milliseconds)</source>
<translation>Varighed af OpenGL overgang (millisekunder)</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="185"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="194"/>
<source>MythGallery Settings (Slideshow)</source>
<translation>MythGallery indstillinger (Slideshow)</translation>
</message>
<message>
- <location filename="../mythgallery/gallerysettings.cpp" line="215"/>
+ <location filename="../mythgallery/gallerysettings.cpp" line="224"/>
<source>MythGallery Settings (General)</source>
<translation>MythGallery indstillinger (Generelt)</translation>
</message>
<message>
- <location filename="../mythgallery/main.cpp" line="45"/>
+ <location filename="../mythgallery/main.cpp" line="44"/>
<source>MythGallery cannot find its start directory.
%1
Check the directory exists, is readable and the setting is correct on MythGallery&apos;s settings page.</source>
View
22 mythtv/bindings/python/MythTV/system.py
@@ -147,16 +147,18 @@ def _fillNone(self):
def _process(self, xml):
for element in xml.getchildren():
- if element.tag in self:
- if (element.text == '') or (element.text is None):
- self[element.tag] = None
- else:
- self[element.tag] = \
- self._trans[self._global_type[element.tag]]\
- (element.text)
- if element.tag in self._groups:
- self.__dict__[element.tag] = \
- eval('self.%s(element)' % element.tag.capitalize())
+ try:
+ if element.tag in self:
+ if (element.text == '') or (element.text is None):
+ self[element.tag] = None
+ else:
+ self[element.tag] = \
+ self._trans[self._global_type[element.tag]]\
+ (element.text)
+ if element.tag in self._groups:
+ self.__dict__[element.tag] = \
+ eval('self.%s(element)' % element.tag.capitalize())
+ except: pass
class VideoMetadata( Metadata ):
_field_order = ['title','subtitle','tagline','description','season',
View
86 mythtv/bindings/python/MythTV/tmdb/tmdb_api.py
@@ -19,7 +19,7 @@
for this api are published at http://api.themoviedb.org/2.1/
'''
-__version__="v0.2.5"
+__version__="v0.2.6"
# 0.1.0 Initial development
# 0.1.1 Alpha Release
# 0.1.2 Added removal of any line-feeds from data
@@ -41,6 +41,8 @@
# 0.2.4 Added width and height attributes to images
# 0.2.5 Added a replace text XPatch extention so that "person" full size images can be created from
# the thumbnail.
+# 0.2.6 Fixed processing publish date when it is a 'UTC' date
+# Code line length clean up
import os, struct, sys, time
import urllib, urllib2
@@ -348,23 +350,38 @@ def __init__(self,
self.config[u'urls'] = {}
# v2.1 api calls
- self.config[u'urls'][u'movie.search'] = u'%(base_url)s/Movie.search/%(language)s/xml/%(apikey)s/%%s' % (self.config)
- self.config[u'urls'][u'tmdbid.search'] = u'%(base_url)s/Movie.getInfo/%(language)s/xml/%(apikey)s/%%s' % (self.config)
- self.config[u'urls'][u'imdb.search'] = u'%(base_url)s/Movie.imdbLookup/%(language)s/xml/%(apikey)s/tt%%s' % (self.config)
- self.config[u'urls'][u'image.search'] = u'%(base_url)s/Movie.getImages/%(language)s/xml/%(apikey)s/%%s' % (self.config)
- self.config[u'urls'][u'person.search'] = u'%(base_url)s/Person.search/%(language)s/xml/%(apikey)s/%%s' % (self.config)
- self.config[u'urls'][u'person.info'] = u'%(base_url)s/Person.getInfo/%(language)s/xml/%(apikey)s/%%s' % (self.config)
- self.config[u'urls'][u'hash.info'] = u'%(base_url)s/Hash.getInfo/%(language)s/xml/%(apikey)s/%%s' % (self.config)
+ self.config[u'urls'][u'movie.search'] = \
+ u'%(base_url)s/Movie.search/%(language)s/xml/%(apikey)s/%%s' % (self.config)
+ self.config[u'urls'][u'tmdbid.search'] = \
+ u'%(base_url)s/Movie.getInfo/%(language)s/xml/%(apikey)s/%%s' % (self.config)
+ self.config[u'urls'][u'imdb.search'] = \
+ u'%(base_url)s/Movie.imdbLookup/%(language)s/xml/%(apikey)s/tt%%s' % (self.config)
+ self.config[u'urls'][u'image.search'] = \
+ u'%(base_url)s/Movie.getImages/%(language)s/xml/%(apikey)s/%%s' % (self.config)
+ self.config[u'urls'][u'person.search'] = \
+ u'%(base_url)s/Person.search/%(language)s/xml/%(apikey)s/%%s' % (self.config)
+ self.config[u'urls'][u'person.info'] = \
+ u'%(base_url)s/Person.getInfo/%(language)s/xml/%(apikey)s/%%s' % (self.config)
+ self.config[u'urls'][u'hash.info'] = \
+ u'%(base_url)s/Hash.getInfo/%(language)s/xml/%(apikey)s/%%s' % (self.config)
# Translation of TMDB elements into MythTV keys/db grabber names
- self.config[u'mythtv_translation'] = {u'actor': u'cast', u'backdrop': u'fanart', u'categories': u'genres', u'director': u'director', u'id': u'inetref', u'name': u'title', u'overview': u'plot', u'rating': u'userrating', u'poster': u'coverart', u'production_countries': u'countries', u'released': u'releasedate', u'runtime': u'runtime', u'url': u'url', u'imdb_id': u'imdb', u'certification': u'movierating', }
+ self.config[u'mythtv_translation'] = {\
+ u'actor': u'cast', u'backdrop': u'fanart', u'categories': u'genres',
+ u'director': u'director', u'id': u'inetref', u'name': u'title',
+ u'overview': u'plot', u'rating': u'userrating', u'poster': u'coverart',
+ u'production_countries': u'countries', u'released': u'releasedate',
+ u'runtime': u'runtime', u'url': u'url', u'imdb_id': u'imdb',
+ u'certification': u'movierating', }
self.config[u'image_extentions'] = ["png", "jpg", "bmp"] # Acceptable image extentions
self.thumbnails = False
self.xml = False
self.pubDateFormat = u'%a, %d %b %Y %H:%M:%S GMT'
self.xmlParser = eTree.HTMLParser(remove_blank_text=True)
self.baseProcessingDir = os.path.dirname( os.path.realpath( __file__ ))
- self.supportedJobList = ["actor", "author", "producer", "executive producer", "director", "cinematographer", "composer", "editor", "casting", ]
+ self.supportedJobList = [\
+ "actor", "author", "producer", "executive producer",
+ "director", "cinematographer", "composer", "editor", "casting", ]
self.tagTranslations = {
'poster': 'coverart',
'backdrop': 'fanart',
@@ -406,9 +423,9 @@ def textUtf8(self, text):
def getCategories(self, categories_et):
- """Takes an element tree Element ('categories') and create a string of comma seperated film
+ """Takes an element tree Element ('categories') and create a string of comma separated film
categories
- return comma seperated sting of film category names
+ return comma separated string of film category names
For example:
<categories>
@@ -430,9 +447,9 @@ def getCategories(self, categories_et):
def getStudios(self, studios_et):
- """Takes an element tree Element ('studios') and create a string of comma seperated film
+ """Takes an element tree Element ('studios') and create a string of comma separated film
studios names
- return comma seperated sting of film studios names
+ return comma separated string of film studios names
For example:
<studios>
@@ -452,9 +469,9 @@ def getStudios(self, studios_et):
return cat
def getProductionCountries(self, countries_et):
- """Takes an element tree Element ('countries') and create a string of comma seperated film
+ """Takes an element tree Element ('countries') and create a string of comma separated film
countries
- return comma seperated sting of countries associated with the film
+ return comma separated string of countries associated with the film
For example:
<countries>
@@ -601,6 +618,9 @@ def searchTitle(self, title, lang=False):
prepend += '\.'
title = prepend + title.lstrip('.')
+ # strip out question marks
+ title = title.replace('?','')
+
title = urllib.quote(title.encode("utf-8"))
url = URL % (title)
@@ -937,16 +957,21 @@ def lastUpdated(self, context, *inputArgs):
try:
if len(args) > 1:
args[1] = args[1].replace(',', u'').replace('.', u'')
- if args[1].find('GMT') != -1:
- args[1] = args[1][:args[1].find('GMT')].strip()
- args[0] = args[0][:args[0].rfind(' ')].strip()
+ for cutOff in ['GMT', 'UTC']:
+ if args[1].find(cutOff) != -1:
+ args[1] = args[1][:args[1].find(cutOff)].strip()
+ args[0] = args[0][:args[0].rfind(' ')].strip()
+ if args[0].find(cutOff) != -1:
+ args[0] = args[0][:args[0].find(cutOff)].strip()
try:
pubdate = time.strptime(args[0], args[1])
except ValueError:
if args[1] == '%a %d %b %Y %H:%M:%S':
pubdate = time.strptime(args[0], '%a %d %B %Y %H:%M:%S')
elif args[1] == '%a %d %B %Y %H:%M:%S':
pubdate = time.strptime(args[0], '%a %d %b %Y %H:%M:%S')
+ else:
+ pubdate = datetime.datetime.now().strftime(self.pubDateFormat)
if len(args) > 2:
return time.strftime(args[2], pubdate)
else:
@@ -1133,8 +1158,19 @@ def __init__(self, apikey, mythtv, interactive, select_first, debug, custom_ui,
super(Videos, self).__init__(apikey, mythtv, interactive, select_first, debug, custom_ui, language, search_all_languages, )
# end __init__()
- error_messages = {'TmdHttpError': u"! Error: A connection error to themoviedb.org was raised (%s)\n", 'TmdXmlError': u"! Error: Invalid XML was received from themoviedb.org (%s)\n", 'TmdBaseError': u"! Error: A user interface error was raised (%s)\n", 'TmdbUiAbort': u"! Error: A user interface input error was raised (%s)\n", }
- key_translation = [{'channel_title': 'channel_title', 'channel_link': 'channel_link', 'channel_description': 'channel_description', 'channel_numresults': 'channel_numresults', 'channel_returned': 'channel_returned', 'channel_startindex': 'channel_startindex'}, {'title': 'item_title', 'item_author': 'item_author', 'releasedate': 'item_pubdate', 'overview': 'item_description', 'url': 'item_link', 'trailer': 'item_url', 'runtime': 'item_duration', 'userrating': 'item_rating', 'width': 'item_width', 'height': 'item_height', 'language': 'item_lang'}]
+ error_messages = {\
+ 'TmdHttpError': u"! Error: A connection error to themoviedb.org was raised (%s)\n",
+ 'TmdXmlError': u"! Error: Invalid XML was received from themoviedb.org (%s)\n",
+ 'TmdBaseError': u"! Error: A user interface error was raised (%s)\n",
+ 'TmdbUiAbort': u"! Error: A user interface input error was raised (%s)\n", }
+ key_translation = [{\
+ 'channel_title': 'channel_title', 'channel_link': 'channel_link', 'channel_description':
+ 'channel_description', 'channel_numresults': 'channel_numresults', 'channel_returned':
+ 'channel_returned', 'channel_startindex': 'channel_startindex'},
+ {'title': 'item_title', 'item_author': 'item_author', 'releasedate':
+ 'item_pubdate', 'overview': 'item_description', 'url': 'item_link', 'trailer': 'item_url',
+ 'runtime': 'item_duration', 'userrating': 'item_rating', 'width': 'item_width', 'height':
+ 'item_height', 'language': 'item_lang'}]
def searchForVideos(self, title, pagenumber):
"""Common name for a video search. Used to interface with MythTV plugin NetVision
@@ -1163,7 +1199,8 @@ def displayMovieData(data):
continue
if key == 'releasedate':
c = time.strptime(data[key],"%Y-%m-%d")
- trailer_data[self.key_translation[1][key]] = time.strftime("%a, %d %b %Y 00:%M:%S GMT",c) # <pubDate>Tue, 14 Jul 2009 17:05:00 GMT</pubDate> <pubdate>Wed, 24 Jun 2009 03:53:00 GMT</pubdate>
+ # <pubDate>Tue, 14 Jul 2009 17:05:00 GMT</pubDate> <pubdate>Wed, 24 Jun 2009 03:53:00 GMT</pubdate>
+ trailer_data[self.key_translation[1][key]] = time.strftime("%a, %d %b %Y 00:%M:%S GMT",c)
continue
trailer_data[self.key_translation[1][key]] = data[key]
else:
@@ -1227,7 +1264,10 @@ def movieData(tmdb_id):
self.key_translation[1][self.thumbnails] = 'item_thumbnail'
# Channel details and search results
- channel = {'channel_title': u'themoviedb.org', 'channel_link': u'http://themoviedb.org', 'channel_description': u'themoviedb.org is an open “wiki-style” movie database', 'channel_numresults': 0, 'channel_returned': self.page_limit, u'channel_startindex': 0}
+ channel = {\
+ 'channel_title': u'themoviedb.org', 'channel_link': u'http://themoviedb.org',
+ 'channel_description': u'themoviedb.org is an open “wiki-style” movie database',
+ 'channel_numresults': 0, 'channel_returned': self.page_limit, u'channel_startindex': 0}
trailers = []
trailer_total = 0
View
2 mythtv/configure
@@ -1471,7 +1471,7 @@ rdft_select="fft"
# decoders / encoders / hardware accelerators
aac_decoder_select="mdct rdft"
aac_encoder_select="mdct"
-aac_latm_decoder_select="aac_decoder"
+aac_latm_decoder_select="aac_decoder aac_latm_parser"
ac3_decoder_select="mdct ac3_parser"
alac_encoder_select="lpc"
amrnb_decoder_select="lsp"
View
16 mythtv/contrib/imports/mirobridge/mirobridge/mirobridge_interpreter_4_0_2.py
@@ -278,6 +278,14 @@ def do_mythtv_getunwatched(self, line):
if hasattr(it.get_parent(), u'url'):
if filetypes.is_torrent_filename(it.get_parent().url):
continue
+
+ # Any item without a proper file name needs to be removed as Miro metadata is corrupt
+ if it.get_filename() == None:
+ it.expire()
+ self.statistics[u'Miro_videos_deleted']+=1
+ logging.info(u'Unwatched video (%s) has been removed from Miro as item had no valid file name' % it.get_title())
+ continue
+
self.printItems(it)
self.videofiles.append(self._get_item_dict(it))
if self.verbose:
@@ -304,6 +312,14 @@ def do_mythtv_getwatched(self, line):
if hasattr(it.get_parent(), u'url'):
if filetypes.is_torrent_filename(it.get_parent().url):
continue
+
+ # Any item without a proper file name needs to be removed as Miro metadata is corrupt
+ if it.get_filename() == None:
+ it.expire()
+ self.statistics[u'Miro_videos_deleted']+=1
+ logging.info(u'Watched video (%s) has been removed from Miro as item had no valid file name' % it.get_title())
+ continue
+
self.printItems(it)
self.videofiles.append(self._get_item_dict(it))
if self.verbose:
View
1 mythtv/external/FFmpeg/libavcodec/Makefile
@@ -61,7 +61,6 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o \
aacpsy.o aactab.o \
psymodel.o iirfilter.o \
mpeg4audio.o
-OBJS-$(CONFIG_AAC_LATM_DECODER) += aaclatmdec.o
OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o
OBJS-$(CONFIG_AC3_DECODER) += ac3dec.o ac3dec_data.o ac3.o
OBJS-$(CONFIG_AC3_ENCODER) += ac3enc.o ac3tab.o ac3.o
View
36 mythtv/external/FFmpeg/libavcodec/aac.h
@@ -42,6 +42,7 @@
#define MAX_ELEM_ID 16
#define TNS_MAX_ORDER 20
+#define MAX_LTP_LONG_SFB 40
enum RawDataBlockType {
TYPE_SCE,
@@ -128,6 +129,17 @@ typedef struct {
#define SCALE_MAX_POS 255 ///< scalefactor index maximum value
#define SCALE_MAX_DIFF 60 ///< maximum scalefactor difference allowed by standard
#define SCALE_DIFF_ZERO 60 ///< codebook index corresponding to zero scalefactor indices difference
+#define POW_SF2_ZERO 200 ///< ff_aac_pow2sf_tab index corresponding to pow(2, 0);
+
+/**
+ * Long Term Prediction
+ */
+typedef struct {
+ int8_t present;
+ int16_t lag;
+ float coef;
+ int8_t used[MAX_LTP_LONG_SFB];
+} LongTermPrediction;
/**
* Individual Channel Stream
@@ -138,6 +150,7 @@ typedef struct {
uint8_t use_kb_window[2]; ///< If set, use Kaiser-Bessel window, otherwise use a sinus window.
int num_window_groups;
uint8_t group_len[8];
+ LongTermPrediction ltp;
const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
const uint8_t *swb_sizes; ///< table of scalefactor band sizes for a particular window
int num_swb; ///< number of scalefactor window bands
@@ -205,14 +218,15 @@ typedef struct {
IndividualChannelStream ics;
TemporalNoiseShaping tns;
Pulse pulse;
- enum BandType band_type[128]; ///< band types
- int band_type_run_end[120]; ///< band type run end points
- float sf[120]; ///< scalefactors
- int sf_idx[128]; ///< scalefactor indices (used by encoder)
- uint8_t zeroes[128]; ///< band is not coded (used by encoder)
- DECLARE_ALIGNED(16, float, coeffs)[1024]; ///< coefficients for IMDCT
- DECLARE_ALIGNED(16, float, saved)[1024]; ///< overlap
- DECLARE_ALIGNED(16, float, ret)[2048]; ///< PCM output
+ enum BandType band_type[128]; ///< band types
+ int band_type_run_end[120]; ///< band type run end points
+ float sf[120]; ///< scalefactors
+ int sf_idx[128]; ///< scalefactor indices (used by encoder)
+ uint8_t zeroes[128]; ///< band is not coded (used by encoder)
+ DECLARE_ALIGNED(16, float, coeffs)[1024]; ///< coefficients for IMDCT
+ DECLARE_ALIGNED(16, float, saved)[1024]; ///< overlap
+ DECLARE_ALIGNED(16, float, ret)[2048]; ///< PCM output
+ DECLARE_ALIGNED(16, int16_t, ltp_state)[3072]; ///< time signal for LTP
PredictorState predictor_state[MAX_PREDICTORS];
} SingleChannelElement;
@@ -251,15 +265,14 @@ typedef struct {
*/
ChannelElement *che[4][MAX_ELEM_ID];
ChannelElement *tag_che_map[4][MAX_ELEM_ID];
- uint8_t tags_seen_this_frame[4][MAX_ELEM_ID];
int tags_mapped;
/** @} */
/**
* @defgroup temporary aligned temporary buffers (We do not want to have these on the stack.)
* @{
*/
- DECLARE_ALIGNED(16, float, buf_mdct)[1024];
+ DECLARE_ALIGNED(16, float, buf_mdct)[2048];
/** @} */
/**
@@ -268,7 +281,9 @@ typedef struct {
*/
FFTContext mdct;
FFTContext mdct_small;
+ FFTContext mdct_ltp;
DSPContext dsp;
+// FmtConvertContext fmt_conv;
int random_state;
/** @} */
@@ -277,7 +292,6 @@ typedef struct {
* @{
*/
float *output_data[MAX_CHANNELS]; ///< Points to each element's 'ret' buffer (PCM output).
- float add_bias; ///< offset for dsp.float_to_int16
float sf_scale; ///< Pre-scale for correct IMDCT and dsp.float_to_int16.
int sf_offset; ///< offset into pow2sf_tab as appropriate for dsp.float_to_int16
/** @} */
View
822 mythtv/external/FFmpeg/libavcodec/aacdec.c
@@ -3,6 +3,10 @@
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
*
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-ffmpeg@jannau.net>
+ *
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
@@ -38,7 +42,7 @@
* Y filterbank - standard
* N (code in SoC repo) filterbank - Scalable Sample Rate
* Y Temporal Noise Shaping
- * N (code in SoC repo) Long Term Prediction
+ * Y Long Term Prediction
* Y intensity stereo
* Y channel coupling
* Y frequency domain prediction
@@ -113,28 +117,11 @@ static const char overread_err[] = "Input buffer exhausted before END element fo
static ChannelElement *get_che(AACContext *ac, int type, int elem_id)
{
- /* Some buggy encoders appear to set all elem_ids to zero and rely on
- channels always occurring in the same order. This is expressly forbidden
- by the spec but we will try to work around it.
- */
- int err_printed = 0;
- while (ac->tags_seen_this_frame[type][elem_id] && elem_id < MAX_ELEM_ID) {
- if (ac->output_configured < OC_LOCKED && !err_printed) {
- av_log(ac->avctx, AV_LOG_WARNING, "Duplicate channel tag found, attempting to remap.\n");
- err_printed = 1;
- }
- elem_id++;
- }
- if (elem_id == MAX_ELEM_ID)
- return NULL;
- ac->tags_seen_this_frame[type][elem_id] = 1;
-
- if (ac->tag_che_map[type][elem_id]) {
+ // For PCE based channel configurations map the channels solely based on tags.
+ if (!ac->m4ac.chan_config) {
return ac->tag_che_map[type][elem_id];
}
- if (ac->tags_mapped >= tags_per_config[ac->m4ac.chan_config]) {
- return NULL;
- }
+ // For indexed channel configurations map the channels solely based on position.
switch (ac->m4ac.chan_config) {
case 7:
if (ac->tags_mapped == 3 && type == TYPE_CPE) {
@@ -190,9 +177,8 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id)
* @return Returns error status. 0 - OK, !0 - error
*/
static av_cold int che_configure(AACContext *ac,
- enum ChannelPosition che_pos[4][MAX_ELEM_ID],
- int type, int id,
- int *channels)
+ enum ChannelPosition che_pos[4][MAX_ELEM_ID],
+ int type, int id, int *channels)
{
if (che_pos[type][id]) {
if (!ac->che[type][id] && !(ac->che[type][id] = av_mallocz(sizeof(ChannelElement))))
@@ -222,9 +208,9 @@ static av_cold int che_configure(AACContext *ac,
* @return Returns error status. 0 - OK, !0 - error
*/
static av_cold int output_configure(AACContext *ac,
- enum ChannelPosition che_pos[4][MAX_ELEM_ID],
- enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
- int channel_config, enum OCStatus oc_type)
+ enum ChannelPosition che_pos[4][MAX_ELEM_ID],
+ enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
+ int channel_config, enum OCStatus oc_type)
{
AVCodecContext *avctx = ac->avctx;
int i, type, channels = 0, ret;
@@ -241,8 +227,7 @@ static av_cold int output_configure(AACContext *ac,
return ret;
}
- memset(ac->tag_che_map, 0, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
- ac->tags_mapped = 0;
+ memset(ac->tag_che_map, 0, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
avctx->channel_layout = aac_channel_layout[channel_config - 1];
} else {
@@ -263,9 +248,6 @@ static av_cold int output_configure(AACContext *ac,
}
memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
- ac->tags_mapped = 4 * MAX_ELEM_ID;
-
- avctx->channel_layout = 0;
}
avctx->channels = channels;
@@ -300,7 +282,8 @@ static void decode_channel_map(enum ChannelPosition *cpe_map,
*
* @return Returns error status. 0 - OK, !0 - error
*/
-static int decode_pce(AACContext *ac, enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
+static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
+ enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
GetBitContext *gb)
{
int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc, sampling_index;
@@ -309,8 +292,8 @@ static int decode_pce(AACContext *ac, enum ChannelPosition new_che_pos[4][MAX_EL
skip_bits(gb, 2); // object_type
sampling_index = get_bits(gb, 4);
- if (ac->m4ac.sampling_index != sampling_index)
- av_log(ac->avctx, AV_LOG_WARNING, "Sample rate index in program config element does not match the sample rate index configured by the container.\n");
+ if (m4ac->sampling_index != sampling_index)
+ av_log(avctx, AV_LOG_WARNING, "Sample rate index in program config element does not match the sample rate index configured by the container.\n");
num_front = get_bits(gb, 4);
num_side = get_bits(gb, 4);
@@ -327,6 +310,10 @@ static int decode_pce(AACContext *ac, enum ChannelPosition new_che_pos[4][MAX_EL
if (get_bits1(gb))
skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround
+ if (get_bits_left(gb) < 4 * (num_front + num_side + num_back + num_lfe + num_assoc_data + num_cc)) {
+ av_log(avctx, AV_LOG_ERROR, overread_err);
+ return -1;
+ }
decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_FRONT, gb, num_front);
decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_SIDE, gb, num_side );
decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_BACK, gb, num_back );
@@ -341,7 +328,7 @@ static int decode_pce(AACContext *ac, enum ChannelPosition new_che_pos[4][MAX_EL
/* comment field, first byte is length */
comment_len = get_bits(gb, 8) * 8;
if (get_bits_left(gb) < comment_len) {
- av_log(ac->avctx, AV_LOG_ERROR, overread_err);
+ av_log(avctx, AV_LOG_ERROR, overread_err);
return -1;
}
skip_bits_long(gb, comment_len);
@@ -356,12 +343,12 @@ static int decode_pce(AACContext *ac, enum ChannelPosition new_che_pos[4][MAX_EL
*
* @return Returns error status. 0 - OK, !0 - error
*/
-static av_cold int set_default_channel_config(AACContext *ac,
- enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
- int channel_config)
+static av_cold int set_default_channel_config(AVCodecContext *avctx,
+ enum ChannelPosition new_che_pos[4][MAX_ELEM_ID],
+ int channel_config)
{
if (channel_config < 1 || channel_config > 7) {
- av_log(ac->avctx, AV_LOG_ERROR, "invalid default channel configuration (%d)\n",
+ av_log(avctx, AV_LOG_ERROR, "invalid default channel configuration (%d)\n",
channel_config);
return -1;
}
@@ -397,41 +384,46 @@ static av_cold int set_default_channel_config(AACContext *ac,
/**
* Decode GA "General Audio" specific configuration; reference: table 4.1.
*
+ * @param ac pointer to AACContext, may be null
+ * @param avctx pointer to AVCCodecContext, used for logging
+ *
* @return Returns error status. 0 - OK, !0 - error
*/
-static int decode_ga_specific_config(AACContext *ac, GetBitContext *gb,
+static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx,
+ GetBitContext *gb,
+ MPEG4AudioConfig *m4ac,
int channel_config)
{
enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
int extension_flag, ret;
if (get_bits1(gb)) { // frameLengthFlag
- av_log_missing_feature(ac->avctx, "960/120 MDCT window is", 1);
+ av_log_missing_feature(avctx, "960/120 MDCT window is", 1);
return -1;
}
if (get_bits1(gb)) // dependsOnCoreCoder
skip_bits(gb, 14); // coreCoderDelay
extension_flag = get_bits1(gb);
- if (ac->m4ac.object_type == AOT_AAC_SCALABLE ||
- ac->m4ac.object_type == AOT_ER_AAC_SCALABLE)
+ if (m4ac->object_type == AOT_AAC_SCALABLE ||
+ m4ac->object_type == AOT_ER_AAC_SCALABLE)
skip_bits(gb, 3); // layerNr
memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
if (channel_config == 0) {
skip_bits(gb, 4); // element_instance_tag
- if ((ret = decode_pce(ac, new_che_pos, gb)))
+ if ((ret = decode_pce(avctx, m4ac, new_che_pos, gb)))
return ret;
} else {
- if ((ret = set_default_channel_config(ac, new_che_pos, channel_config)))
+ if ((ret = set_default_channel_config(avctx, new_che_pos, channel_config)))
return ret;
}
- if ((ret = output_configure(ac, ac->che_pos, new_che_pos, channel_config, OC_GLOBAL_HDR)))
+ if (ac && (ret = output_configure(ac, ac->che_pos, new_che_pos, channel_config, OC_GLOBAL_HDR)))
return ret;
if (extension_flag) {
- switch (ac->m4ac.object_type) {
+ switch (m4ac->object_type) {
case AOT_ER_BSAC:
skip_bits(gb, 5); // numOfSubFrame
skip_bits(gb, 11); // layer_length
@@ -454,42 +446,58 @@ static int decode_ga_specific_config(AACContext *ac, GetBitContext *gb,
/**
* Decode audio specific configuration; reference: table 1.13.
*
+ * @param ac pointer to AACContext, may be null
+ * @param avctx pointer to AVCCodecContext, used for logging
+ * @param m4ac pointer to MPEG4AudioConfig, used for parsing
* @param data pointer to AVCodecContext extradata
* @param data_size size of AVCCodecContext extradata
*
- * @return Returns error status. 0 - OK, !0 - error
+ * @return Returns error status or number of consumed bits. <0 - error
*/
-static int decode_audio_specific_config(AACContext *ac, void *data,
- int data_size)
+static int decode_audio_specific_config(AACContext *ac,
+ AVCodecContext *avctx,
+ MPEG4AudioConfig *m4ac,
+ const uint8_t *data, int data_size, int asclen)
{
GetBitContext gb;
int i;
+ av_log(avctx, AV_LOG_DEBUG, "extradata size %d\n", avctx->extradata_size);
+ for (i = 0; i < avctx->extradata_size; i++)
+ av_log(avctx, AV_LOG_DEBUG, "%02x ", avctx->extradata[i]);
+ av_log(avctx, AV_LOG_DEBUG, "\n");
+
init_get_bits(&gb, data, data_size * 8);
- if ((i = ff_mpeg4audio_get_config(&ac->m4ac, data, data_size)) < 0)
+ if ((i = ff_mpeg4audio_get_config(m4ac, data, asclen/8)) < 0)
return -1;
- if (ac->m4ac.sampling_index > 12) {
- av_log(ac->avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", ac->m4ac.sampling_index);
+ if (m4ac->sampling_index > 12) {
+ av_log(avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", m4ac->sampling_index);
return -1;
}
- if (ac->m4ac.sbr == 1 && ac->m4ac.ps == -1)
- ac->m4ac.ps = 1;
+ if (m4ac->sbr == 1 && m4ac->ps == -1)
+ m4ac->ps = 1;
skip_bits_long(&gb, i);
- switch (ac->m4ac.object_type) {
+ switch (m4ac->object_type) {
case AOT_AAC_MAIN:
case AOT_AAC_LC:
- if (decode_ga_specific_config(ac, &gb, ac->m4ac.chan_config))
+ case AOT_AAC_LTP:
+ if (decode_ga_specific_config(ac, avctx, &gb, m4ac, m4ac->chan_config))
return -1;
break;
default:
- av_log(ac->avctx, AV_LOG_ERROR, "Audio object type %s%d is not supported.\n",
- ac->m4ac.sbr == 1? "SBR+" : "", ac->m4ac.object_type);
+ av_log(avctx, AV_LOG_ERROR, "Audio object type %s%d is not supported.\n",
+ m4ac->sbr == 1? "SBR+" : "", m4ac->object_type);
return -1;
}
- return 0;
+
+ av_log(avctx, AV_LOG_DEBUG, "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n",
+ m4ac->object_type, m4ac->chan_config, m4ac->sampling_index,
+ m4ac->sample_rate, m4ac->sbr, m4ac->ps);
+
+ return get_bits_count(&gb);
}
/**
@@ -521,6 +529,22 @@ static void reset_all_predictors(PredictorState *ps)
reset_predict_state(&ps[i]);
}
+static int sample_rate_idx (int rate)
+{
+ if (92017 <= rate) return 0;
+ else if (75132 <= rate) return 1;
+ else if (55426 <= rate) return 2;
+ else if (46009 <= rate) return 3;
+ else if (37566 <= rate) return 4;
+ else if (27713 <= rate) return 5;
+ else if (23004 <= rate) return 6;
+ else if (18783 <= rate) return 7;
+ else if (13856 <= rate) return 8;
+ else if (11502 <= rate) return 9;
+ else if (9391 <= rate) return 10;
+ else return 11;
+}
+
static void reset_predictor_group(PredictorState *ps, int group_num)
{
int i;
@@ -542,8 +566,31 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
ac->m4ac.sample_rate = avctx->sample_rate;
if (avctx->extradata_size > 0) {
- if (decode_audio_specific_config(ac, avctx->extradata, avctx->extradata_size))
+ if (decode_audio_specific_config(ac, ac->avctx, &ac->m4ac,
+ avctx->extradata,
+ avctx->extradata_size, 8*avctx->extradata_size) < 0)
return -1;
+ } else {
+ int sr, i;
+ enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
+
+ sr = sample_rate_idx(avctx->sample_rate);
+ ac->m4ac.sampling_index = sr;
+ ac->m4ac.channels = avctx->channels;
+ ac->m4ac.sbr = -1;
+ ac->m4ac.ps = -1;
+
+ for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++)
+ if (ff_mpeg4audio_channels[i] == avctx->channels)
+ break;
+ if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) {
+ i = 0;
+ }
+ ac->m4ac.chan_config = i;
+
+ if (ac->m4ac.chan_config) {
+ set_default_channel_config(avctx, new_che_pos, ac->m4ac.chan_config);
+ }
}
avctx->sample_fmt = SAMPLE_FMT_S16;
@@ -563,32 +610,20 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
ff_aac_sbr_init();
dsputil_init(&ac->dsp, avctx);
+// ff_fmt_convert_init(&ac->fmt_conv, avctx);
ac->random_state = 0x1f2e3d4c;
- // -1024 - Compensate wrong IMDCT method.
- // 32768 - Required to scale values to the correct range for the bias method
- // for float to int16 conversion.
-
- if (ac->dsp.float_to_int16_interleave == ff_float_to_int16_interleave_c) {
- ac->add_bias = 385.0f;
- ac->sf_scale = 1. / (-1024. * 32768.);
- ac->sf_offset = 0;
- } else {
- ac->add_bias = 0.0f;
- ac->sf_scale = 1. / -1024.;
- ac->sf_offset = 60;
- }
-
ff_aac_tableinit();
INIT_VLC_STATIC(&vlc_scalefactors,7,FF_ARRAY_ELEMS(ff_aac_scalefactor_code),
ff_aac_scalefactor_bits, sizeof(ff_aac_scalefactor_bits[0]), sizeof(ff_aac_scalefactor_bits[0]),
ff_aac_scalefactor_code, sizeof(ff_aac_scalefactor_code[0]), sizeof(ff_aac_scalefactor_code[0]),
352);
- ff_mdct_init(&ac->mdct, 11, 1, 1.0);
- ff_mdct_init(&ac->mdct_small, 8, 1, 1.0);
+ ff_mdct_init(&ac->mdct, 11, 1, 1.0/1024.0);
+ ff_mdct_init(&ac->mdct_small, 8, 1, 1.0/128.0);
+ ff_mdct_init(&ac->mdct_ltp, 11, 0, -2.0);
// window initialization
ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024);
ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128);
@@ -638,6 +673,20 @@ static int decode_prediction(AACContext *ac, IndividualChannelStream *ics,
}
/**
+ * Decode Long Term Prediction data; reference: table 4.xx.
+ */
+static void decode_ltp(AACContext *ac, LongTermPrediction *ltp,
+ GetBitContext *gb, uint8_t max_sfb)
+{
+ int sfb;
+
+ ltp->lag = get_bits(gb, 11);
+ ltp->coef = ltp_coef[get_bits(gb, 3)];
+ for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++)
+ ltp->used[sfb] = get_bits1(gb);
+}
+
+/**
* Decode Individual Channel Stream info; reference: table 4.6.
*
* @param common_window Channels have independent [0], or shared [1], Individual Channel Stream information.
@@ -691,9 +740,8 @@ static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics,
memset(ics, 0, sizeof(IndividualChannelStream));
return -1;
} else {
- av_log_missing_feature(ac->avctx, "Predictor bit set but LTP is", 1);
- memset(ics, 0, sizeof(IndividualChannelStream));
- return -1;
+ if ((ics->ltp.present = get_bits(gb, 1)))
+ decode_ltp(ac, &ics->ltp, gb, ics->max_sfb);
}
}
}
@@ -771,9 +819,9 @@ static int decode_scalefactors(AACContext *ac, float sf[120], GetBitContext *gb,
enum BandType band_type[120],
int band_type_run_end[120])
{
- const int sf_offset = ac->sf_offset + (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE ? 12 : 0);
int g, i, idx = 0;
- int offset[3] = { global_gain, global_gain - 90, 100 };
+ int offset[3] = { global_gain, global_gain - 90, 0 };
+ int clipped_offset;
int noise_flag = 1;
static const char *sf_str[3] = { "Global gain", "Noise gain", "Intensity stereo position" };
for (g = 0; g < ics->num_window_groups; g++) {
@@ -785,25 +833,31 @@ static int decode_scalefactors(AACContext *ac, float sf[120], GetBitContext *gb,
} else if ((band_type[idx] == INTENSITY_BT) || (band_type[idx] == INTENSITY_BT2)) {
for (; i < run_end; i++, idx++) {
offset[2] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60;
- if (offset[2] > 255U) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "%s (%d) out of range.\n", sf_str[2], offset[2]);
- return -1;
+ clipped_offset = av_clip(offset[2], -155, 100);
+ if (offset[2] != clipped_offset) {
+/* av_log_ask_for_sample(ac->avctx, "Intensity stereo "
+ "position clipped (%d -> %d).\nIf you heard an "
+ "audible artifact, there may be a bug in the "
+ "decoder. ", offset[2], clipped_offset);
+*/
}
- sf[idx] = ff_aac_pow2sf_tab[-offset[2] + 300];
+ sf[idx] = ff_aac_pow2sf_tab[-clipped_offset + POW_SF2_ZERO];
}
} else if (band_type[idx] == NOISE_BT) {
for (; i < run_end; i++, idx++) {
if (noise_flag-- > 0)
offset[1] += get_bits(gb, 9) - 256;
else
offset[1] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60;
- if (offset[1] > 255U) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "%s (%d) out of range.\n", sf_str[1], offset[1]);
- return -1;
+ clipped_offset = av_clip(offset[1], -100, 155);
+ if (offset[1] != clipped_offset) {
+/* av_log_ask_for_sample(ac->avctx, "Noise gain clipped "
+ "(%d -> %d).\nIf you heard an audible "
+ "artifact, there may be a bug in the decoder. ",
+ offset[1], clipped_offset);
+*/
}
- sf[idx] = -ff_aac_pow2sf_tab[offset[1] + sf_offset + 100];
+ sf[idx] = -ff_aac_pow2sf_tab[clipped_offset + POW_SF2_ZERO];
}
} else {
for (; i < run_end; i++, idx++) {
@@ -813,7 +867,7 @@ static int decode_scalefactors(AACContext *ac, float sf[120], GetBitContext *gb,
"%s (%d) out of range.\n", sf_str[0], offset[0]);
return -1;
}
- sf[idx] = -ff_aac_pow2sf_tab[ offset[0] + sf_offset];
+ sf[idx] = -ff_aac_pow2sf_tab[offset[0] - 100 + POW_SF2_ZERO];
}
}
}
@@ -954,19 +1008,19 @@ static inline float *VMUL4S(float *dst, const float *v, unsigned idx,
union float754 s = { .f = *scale };
union float754 t;
- t.i = s.i ^ (sign & 1<<31);
+ t.i = s.i ^ (sign & 1U<<31);
*dst++ = v[idx & 3] * t.f;
sign <<= nz & 1; nz >>= 1;
- t.i = s.i ^ (sign & 1<<31);
+ t.i = s.i ^ (sign & 1U<<31);
*dst++ = v[idx>>2 & 3] * t.f;
sign <<= nz & 1; nz >>= 1;
- t.i = s.i ^ (sign & 1<<31);
+ t.i = s.i ^ (sign & 1U<<31);
*dst++ = v[idx>>4 & 3] * t.f;
sign <<= nz & 1; nz >>= 1;
- t.i = s.i ^ (sign & 1<<31);
+ t.i = s.i ^ (sign & 1U<<31);
*dst++ = v[idx>>6 & 3] * t.f;
return dst;
@@ -1063,9 +1117,6 @@ static int decode_spectrum_and_dequant(AACContext *ac, float coef[1024],
UPDATE_CACHE(re, gb);
GET_VLC(code, re, gb, vlc_tab, 8, 2);
-#if MIN_CACHE_BITS < 20
- UPDATE_CACHE(re, gb);
-#endif
cb_idx = cb_vector_idx[code];
nnz = cb_idx >> 8 & 15;
bits = SHOW_UBITS(re, gb, nnz) << (32-nnz);
@@ -1158,20 +1209,15 @@ static int decode_spectrum_and_dequant(AACContext *ac, float coef[1024],
return -1;
}
-#if MIN_CACHE_BITS < 21
- LAST_SKIP_BITS(re, gb, b + 1);
- UPDATE_CACHE(re, gb);
-#else
SKIP_BITS(re, gb, b + 1);
-#endif
b += 4;
n = (1 << b) + SHOW_UBITS(re, gb, b);
LAST_SKIP_BITS(re, gb, b);
- *icf++ = cbrt_tab[n] | (bits & 1<<31);
+ *icf++ = cbrt_tab[n] | (bits & 1U<<31);
bits <<= 1;
} else {
unsigned v = ((const uint32_t*)vq)[cb_idx & 15];
- *icf++ = (bits & 1<<31) | v;
+ *icf++ = (bits & 1U<<31) | v;
bits <<= !!v;
}
cb_idx >>= 4;
@@ -1232,8 +1278,7 @@ static av_always_inline float flt16_trunc(float pf)
}
static av_always_inline void predict(PredictorState *ps, float *coef,
- float sf_scale, float inv_sf_scale,
- int output_enable)
+ int output_enable)
{
const float a = 0.953125; // 61.0 / 64
const float alpha = 0.90625; // 29.0 / 32
@@ -1249,9 +1294,9 @@ static av_always_inline void predict(PredictorState *ps, float *coef,
pv = flt16_round(k1 * r0 + k2 * r1);
if (output_enable)
- *coef += pv * sf_scale;
+ *coef += pv;
- e0 = *coef * inv_sf_scale;
+ e0 = *coef;
e1 = e0 - k1 * r0;
ps->cor1 = flt16_trunc(alpha * cor1 + r1 * e1);
@@ -1269,7 +1314,6 @@ static av_always_inline void predict(PredictorState *ps, float *coef,
static void apply_prediction(AACContext *ac, SingleChannelElement *sce)
{
int sfb, k;
- float sf_scale = ac->sf_scale, inv_sf_scale = 1 / ac->sf_scale;
if (!sce->ics.predictor_initialized) {
reset_all_predictors(sce->predictor_state);
@@ -1280,7 +1324,6 @@ static void apply_prediction(AACContext *ac, SingleChannelElement *sce)
for (sfb = 0; sfb < ff_aac_pred_sfb_max[ac->m4ac.sampling_index]; sfb++) {
for (k = sce->ics.swb_offset[sfb]; k < sce->ics.swb_offset[sfb + 1]; k++) {
predict(&sce->predictor_state[k], &sce->coeffs[k],
- sf_scale, inv_sf_scale,
sce->ics.predictor_present && sce->ics.prediction_used[sfb]);
}
}
@@ -1386,13 +1429,13 @@ static void apply_mid_side_stereo(AACContext *ac, ChannelElement *cpe)
* [1] mask is decoded from bitstream; [2] mask is all 1s;
* [3] reserved for scalable AAC
*/
-static void apply_intensity_stereo(ChannelElement *cpe, int ms_present)
+static void apply_intensity_stereo(AACContext *ac, ChannelElement *cpe, int ms_present)
{
const IndividualChannelStream *ics = &cpe->ch[1].ics;
SingleChannelElement *sce1 = &cpe->ch[1];
float *coef0 = cpe->ch[0].coeffs, *coef1 = cpe->ch[1].coeffs;
const uint16_t *offsets = ics->swb_offset;
- int g, group, i, k, idx = 0;
+ int g, group, i, idx = 0;
int c;
float scale;
for (g = 0; g < ics->num_window_groups; g++) {
@@ -1405,8 +1448,10 @@ static void apply_intensity_stereo(ChannelElement *cpe, int ms_present)
c *= 1 - 2 * cpe->ms_mask[idx];
scale = c * sce1->sf[idx];
for (group = 0; group < ics->group_len[g]; group++)
- for (k = offsets[i]; k < offsets[i + 1]; k++)
- coef1[group * 128 + k] = scale * coef0[group * 128 + k];
+ ac->dsp.vector_fmul_scalar(coef1 + group * 128 + offsets[i],
+ coef0 + group * 128 + offsets[i],
+ scale,
+ offsets[i + 1] - offsets[i]);
}
} else {
int bt_run_end = sce1->band_type_run_end[idx];
@@ -1435,6 +1480,9 @@ static int decode_cpe(AACContext *ac, GetBitContext *gb, ChannelElement *cpe)
i = cpe->ch[1].ics.use_kb_window[0];
cpe->ch[1].ics = cpe->ch[0].ics;
cpe->ch[1].ics.use_kb_window[1] = i;
+ if (cpe->ch[1].ics.predictor_present && (ac->m4ac.object_type != AOT_AAC_MAIN))
+ if ((cpe->ch[1].ics.ltp.present = get_bits(gb, 1)))
+ decode_ltp(ac, &cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb);
ms_present = get_bits(gb, 2);
if (ms_present == 3) {
av_log(ac->avctx, AV_LOG_ERROR, "ms_present = 3 is reserved.\n");
@@ -1456,7 +1504,7 @@ static int decode_cpe(AACContext *ac, GetBitContext *gb, ChannelElement *cpe)
}
}
- apply_intensity_stereo(cpe, ms_present);
+ apply_intensity_stereo(ac, cpe, ms_present);
return 0;
}
@@ -1674,6 +1722,7 @@ static void apply_tns(float coef[1024], TemporalNoiseShaping *tns,
int w, filt, m, i;
int bottom, top, order, start, end, size, inc;
float lpc[TNS_MAX_ORDER];
+ float tmp[TNS_MAX_ORDER];
for (w = 0; w < ics->num_windows; w++) {
bottom = ics->num_swb;
@@ -1699,18 +1748,129 @@ static void apply_tns(float coef[1024], TemporalNoiseShaping *tns,
}
start += w * 128;
- // ar filter
- for (m = 0; m < size; m++, start += inc)
- for (i = 1; i <= FFMIN(m, order); i++)
- coef[start] -= coef[start - i * inc] * lpc[i - 1];
+ if (decode) {
+ // ar filter
+ for (m = 0; m < size; m++, start += inc)
+ for (i = 1; i <= FFMIN(m, order); i++)
+ coef[start] -= coef[start - i * inc] * lpc[i - 1];
+ } else {
+ // ma filter
+ for (m = 0; m < size; m++, start += inc) {
+ tmp[0] = coef[start];
+ for (i = 1; i <= FFMIN(m, order); i++)
+ coef[start] += tmp[i] * lpc[i - 1];
+ for (i = order; i > 0; i--)
+ tmp[i] = tmp[i - 1];
+ }
+ }
}
}
}
+static void vector_fmul(float *dst, const float *src0, const float *src1, int len){
+ int i;
+ for(i=0; i<len; i++)
+ dst[i] = src0[i] * src1[i];
+}
+
+/**
+ * Apply windowing and MDCT to obtain the spectral
+ * coefficient from the predicted sample by LTP.
+ */
+static void windowing_and_mdct_ltp(AACContext *ac, float *out,
+ float *in, IndividualChannelStream *ics)
+{
+ const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024;
+ const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;
+ const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024;
+ const float *swindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128;
+
+ if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) {
+ vector_fmul(in, in, lwindow_prev, 1024);
+ } else {
+ memset(in, 0, 448 * sizeof(float));
+ vector_fmul(in + 448, in + 448, swindow_prev, 128);
+ }
+ if (ics->window_sequence[0] != LONG_START_SEQUENCE) {
+ ac->dsp.vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
+ } else {
+ ac->dsp.vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
+ memset(in + 1024 + 576, 0, 448 * sizeof(float));
+ }
+ ac->mdct_ltp.mdct_calc(&ac->mdct_ltp, out, in);
+}
+
+/**
+ * Apply the long term prediction
+ */
+static void apply_ltp(AACContext *ac, SingleChannelElement *sce)
+{
+ const LongTermPrediction *ltp = &sce->ics.ltp;
+ const uint16_t *offsets = sce->ics.swb_offset;
+ int i, sfb;
+
+ if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
+ float *predTime = sce->ret;
+ float *predFreq = ac->buf_mdct;
+ int16_t num_samples = 2048;
+
+ if (ltp->lag < 1024)
+ num_samples = ltp->lag + 1024;
+ for (i = 0; i < num_samples; i++)
+ predTime[i] = sce->ltp_state[i + 2048 - ltp->lag] * ltp->coef;
+ memset(&predTime[i], 0, (2048 - i) * sizeof(float));
+
+ windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics);
+
+ if (sce->tns.present)
+ apply_tns(predFreq, &sce->tns, &sce->ics, 0);
+
+ for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
+ if (ltp->used[sfb])
+ for (i = offsets[sfb]; i < offsets[sfb + 1]; i++)
+ sce->coeffs[i] += predFreq[i];
+ }
+}
+
+/**
+ * Update the LTP buffer for next frame
+ */
+static void update_ltp(AACContext *ac, SingleChannelElement *sce)
+{
+ IndividualChannelStream *ics = &sce->ics;
+ float *saved = sce->saved;
+ float *saved_ltp = sce->coeffs;
+ const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024;
+ const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;
+ int i;
+
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ memcpy(saved_ltp, saved, 512 * sizeof(float));
+ memset(saved_ltp + 576, 0, 448 * sizeof(float));
+ ac->dsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64);
+ for (i = 0; i < 64; i++)
+ saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * swindow[63 - i];
+ } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
+ memcpy(saved_ltp, ac->buf_mdct + 512, 448 * sizeof(float));
+ memset(saved_ltp + 576, 0, 448 * sizeof(float));
+ ac->dsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64);
+ for (i = 0; i < 64; i++)
+ saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * swindow[63 - i];
+ } else { // LONG_STOP or ONLY_LONG
+ ac->dsp.vector_fmul_reverse(saved_ltp, ac->buf_mdct + 512, &lwindow[512], 512);
+ for (i = 0; i < 512; i++)
+ saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * lwindow[511 - i];
+ }
+
+ memcpy(sce->ltp_state, sce->ltp_state+1024, 1024 * sizeof(*sce->ltp_state));
+ memcpy(sce->ltp_state+1024, sce->ret, 1024 * sizeof(*sce->ltp_state));
+ memcpy(sce->ltp_state+2048, saved_ltp, 1024 * sizeof(*sce->ltp_state));
+}
+
/**
* Conduct IMDCT and windowing.
*/
-static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce, float bias)
+static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce)
{
IndividualChannelStream *ics = &sce->ics;
float *in = sce->coeffs;
@@ -1726,9 +1886,9 @@ static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce, float
// imdct
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
for (i = 0; i < 1024; i += 128)
- ff_imdct_half(&ac->mdct_small, buf + i, in + i);
+ ac->mdct_small.imdct_half(&ac->mdct_small, buf + i, in + i);
} else
- ff_imdct_half(&ac->mdct, buf, in);
+ ac->mdct.imdct_half(&ac->mdct, buf, in);
/* window overlapping
* NOTE: To simplify the overlapping code, all 'meaningless' short to long
@@ -1738,32 +1898,29 @@ static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce, float
*/
if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
(ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
- ac->dsp.vector_fmul_window( out, saved, buf, lwindow_prev, bias, 512);
+ ac->dsp.vector_fmul_window( out, saved, buf, lwindow_prev, 0.0f, 512);
} else {
- for (i = 0; i < 448; i++)
- out[i] = saved[i] + bias;
+ memcpy( out, saved, 448 * sizeof(float));
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- ac->dsp.vector_fmul_window(out + 448 + 0*128, saved + 448, buf + 0*128, swindow_prev, bias, 64);
- ac->dsp.vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow, bias, 64);
- ac->dsp.vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow, bias, 64);
- ac->dsp.vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow, bias, 64);
- ac->dsp.vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, swindow, bias, 64);
+ ac->dsp.vector_fmul_window(out + 448 + 0*128, saved + 448, buf + 0*128, swindow_prev, 0.0f, 64);
+ ac->dsp.vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow, 0.0f, 64);
+ ac->dsp.vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow, 0.0f, 64);
+ ac->dsp.vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow, 0.0f, 64);
+ ac->dsp.vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, swindow, 0.0f, 64);
memcpy( out + 448 + 4*128, temp, 64 * sizeof(float));
} else {
- ac->dsp.vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, bias, 64);
- for (i = 576; i < 1024; i++)
- out[i] = buf[i-512] + bias;
+ ac->dsp.vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, 0.0f, 64);
+ memcpy( out + 576, buf + 64, 448 * sizeof(float));
}
}
// buffer update
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- for (i = 0; i < 64; i++)
- saved[i] = temp[64 + i] - bias;
- ac->dsp.vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 0, 64);
- ac->dsp.vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 0, 64);
- ac->dsp.vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 0, 64);
+ memcpy( saved, temp + 64, 64 * sizeof(float));
+ ac->dsp.vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 0.0f, 64);
+ ac->dsp.vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 0.0f, 64);
+ ac->dsp.vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 0.0f, 64);
memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(float));
} else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
memcpy( saved, buf + 512, 448 * sizeof(float));
@@ -1820,13 +1977,12 @@ static void apply_independent_coupling(AACContext *ac,
{
int i;
const float gain = cce->coup.gain[index][0];
- const float bias = ac->add_bias;
const float *src = cce->ch[0].ret;
float *dest = target->ret;
const int len = 1024 << (ac->m4ac.sbr == 1);
for (i = 0; i < len; i++)
- dest[i] += gain * (src[i] - bias);
+ dest[i] += gain * src[i];
}
/**
@@ -1870,23 +2026,34 @@ static void apply_channel_coupling(AACContext *ac, ChannelElement *cc,
static void spectral_to_sample(AACContext *ac)
{
int i, type;
- float imdct_bias = (ac->m4ac.sbr <= 0) ? ac->add_bias : 0.0f;
for (type = 3; type >= 0; type--) {
for (i = 0; i < MAX_ELEM_ID; i++) {
ChannelElement *che = ac->che[type][i];
if (che) {
if (type <= TYPE_CPE)
apply_channel_coupling(ac, che, type, i, BEFORE_TNS, apply_dependent_coupling);
+ if (ac->m4ac.object_type == AOT_AAC_LTP) {
+ if (che->ch[0].ics.predictor_present) {
+ if (che->ch[0].ics.ltp.present)
+ apply_ltp(ac, &che->ch[0]);
+ if (che->ch[1].ics.ltp.present && type == TYPE_CPE)
+ apply_ltp(ac, &che->ch[1]);
+ }
+ }
if (che->ch[0].tns.present)
apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1);
if (che->ch[1].tns.present)
apply_tns(che->ch[1].coeffs, &che->ch[1].tns, &che->ch[1].ics, 1);
if (type <= TYPE_CPE)
apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, apply_dependent_coupling);
if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
- imdct_and_windowing(ac, &che->ch[0], imdct_bias);
+ imdct_and_windowing(ac, &che->ch[0]);
+ if (ac->m4ac.object_type == AOT_AAC_LTP)
+ update_ltp(ac, &che->ch[0]);
if (type == TYPE_CPE) {
- imdct_and_windowing(ac, &che->ch[1], imdct_bias);
+ imdct_and_windowing(ac, &che->ch[1]);
+ if (ac->m4ac.object_type == AOT_AAC_LTP)
+ update_ltp(ac, &che->ch[1]);
}
if (ac->m4ac.sbr > 0) {
ff_sbr_apply(ac, &che->sbr, type, che->ch[0].ret, che->ch[1].ret);
@@ -1906,24 +2073,25 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb)
size = ff_aac_parse_header(gb, &hdr_info);
if (size > 0) {
- if (ac->output_configured != OC_LOCKED && hdr_info.chan_config) {
+ if (hdr_info.chan_config) {
enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
ac->m4ac.chan_config = hdr_info.chan_config;
- if (set_default_channel_config(ac, new_che_pos, hdr_info.chan_config))
+ if (set_default_channel_config(ac->avctx, new_che_pos, hdr_info.chan_config))
return -7;
if (output_configure(ac, ac->che_pos, new_che_pos, hdr_info.chan_config, OC_TRIAL_FRAME))
return -7;
} else if (ac->output_configured != OC_LOCKED) {
+ ac->m4ac.chan_config = 0;
ac->output_configured = OC_NONE;
}
if (ac->output_configured != OC_LOCKED) {
ac->m4ac.sbr = -1;
ac->m4ac.ps = -1;
+ ac->m4ac.sample_rate = hdr_info.sample_rate;
+ ac->m4ac.sampling_index = hdr_info.sampling_index;
+ ac->m4ac.object_type = hdr_info.object_type;
}
- ac->m4ac.sample_rate = hdr_info.sample_rate;
- ac->m4ac.sampling_index = hdr_info.sampling_index;
- ac->m4ac.object_type = hdr_info.object_type;
if (!ac->avctx->sample_rate)
ac->avctx->sample_rate = hdr_info.sample_rate;
if (hdr_info.num_aac_frames == 1) {
@@ -1937,24 +2105,17 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb)
return size;
}
-static int aac_decode_frame(AVCodecContext *avctx, void *data,
- int *data_size, AVPacket *avpkt)
+static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
+ int *data_size, GetBitContext *gb)
{
- const uint8_t *buf = avpkt->data;
- int buf_size = avpkt->size;
AACContext *ac = avctx->priv_data;
ChannelElement *che = NULL, *che_prev = NULL;
- GetBitContext gb;
enum RawDataBlockType elem_type, elem_type_prev = TYPE_END;
int err, elem_id, data_size_tmp;
- int buf_consumed;
- int samples = 0, multiplier;
- int buf_offset;
+ int samples = 0, multiplier, audio_found = 0;
- init_get_bits(&gb, buf, buf_size * 8);
-
- if (show_bits(&gb, 12) == 0xfff) {
- if (parse_adts_frame_header(ac, &gb) < 0) {
+ if (show_bits(gb, 12) == 0xfff) {
+ if (parse_adts_frame_header(ac, gb) < 0) {
av_log(avctx, AV_LOG_ERROR, "Error decoding AAC frame header.\n");
return -1;
}
@@ -1964,10 +2125,10 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data,
}
}
- memset(ac->tags_seen_this_frame, 0, sizeof(ac->tags_seen_this_frame));
+ ac->tags_mapped = 0;
// parse
- while ((elem_type = get_bits(&gb, 3)) != TYPE_END) {
- elem_id = get_bits(&gb, 4);
+ while ((elem_type = get_bits(gb, 3)) != TYPE_END) {
+ elem_id = get_bits(gb, 4);
if (elem_type < TYPE_DSE) {
if (!(che=get_che(ac, elem_type, elem_id))) {
@@ -1981,29 +2142,32 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data,
switch (elem_type) {
case TYPE_SCE:
- err = decode_ics(ac, &che->ch[0], &gb, 0, 0);
+ err = decode_ics(ac, &che->ch[0], gb, 0, 0);
+ audio_found = 1;
break;
case TYPE_CPE:
- err = decode_cpe(ac, &gb, che);
+ err = decode_cpe(ac, gb, che);
+ audio_found = 1;
break;
case TYPE_CCE:
- err = decode_cce(ac, &gb, che);
+ err = decode_cce(ac, gb, che);
break;
case TYPE_LFE:
- err = decode_ics(ac, &che->ch[0], &gb, 0, 0);
+ err = decode_ics(ac, &che->ch[0], gb, 0, 0);
+ audio_found = 1;
break;
case TYPE_DSE:
- err = skip_data_stream_element(ac, &gb);
+ err = skip_data_stream_element(ac, gb);
break;
case TYPE_PCE: {
enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
- if ((err = decode_pce(ac, new_che_pos, &gb)))
+ if ((err = decode_pce(avctx, &ac->m4ac, new_che_pos, gb)))
break;
if (ac->output_configured > OC_TRIAL_PCE)
av_log(avctx, AV_LOG_ERROR,
@@ -2015,13 +2179,13 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data,
case TYPE_FIL:
if (elem_id == 15)
- elem_id += get_bits(&gb, 8) - 1;
- if (get_bits_left(&gb) < 8 * elem_id) {
+ elem_id += get_bits(gb, 8) - 1;
+ if (get_bits_left(gb) < 8 * elem_id) {
av_log(avctx, AV_LOG_ERROR, overread_err);
return -1;
}
while (elem_id > 0)
- elem_id -= decode_extension_payload(ac, &gb, elem_id, che_prev, elem_type_prev);
+ elem_id -= decode_extension_payload(ac, gb, elem_id, che_prev, elem_type_prev);
err = 0; /* FIXME */
break;
@@ -2036,7 +2200,7 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data,
if (err)
return err;
- if (get_bits_left(&gb) < 3) {
+ if (get_bits_left(gb) < 3) {
av_log(avctx, AV_LOG_ERROR, overread_err);
return -1;
}
@@ -2063,9 +2227,30 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data,
if (samples)
ac->dsp.float_to_int16_interleave(data, (const float **)ac->output_data, samples, avctx->channels);
- if (ac->output_configured)
+// if (samples)
+// ac->fmt_conv.float_to_int16_interleave(data, (const float **)ac->output_data, samples, avctx->channels);
+
+ if (ac->output_configured && audio_found)
ac->output_configured = OC_LOCKED;
+ return 0;
+}
+
+static int aac_decode_frame(AVCodecContext *avctx, void *data,
+ int *data_size, AVPacket *avpkt)
+{
+ const uint8_t *buf = avpkt->data;
+ int buf_size = avpkt->size;
+ GetBitContext gb;
+ int buf_consumed;
+ int buf_offset;
+ int err;
+
+ init_get_bits(&gb, buf, buf_size * 8);
+
+ if ((err = aac_decode_frame_int(avctx, data, data_size, &gb)) < 0)
+ return err;
+
buf_consumed = (get_bits_count(&gb) + 7) >> 3;
for (buf_offset = buf_consumed; buf_offset < buf_size; buf_offset++)
if (buf[buf_offset])
@@ -2089,9 +2274,270 @@ static av_cold int aac_decode_close(AVCodecContext *avctx)
ff_mdct_end(&ac->mdct);
ff_mdct_end(&ac->mdct_small);
+ ff_mdct_end(&ac->mdct_ltp);
return 0;
}
+
+#define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word
+
+struct LATMContext {
+ AACContext aac_ctx; ///< containing AACContext
+ int initialized; ///< initilized after a valid extradata was seen
+
+ // parser data
+ int audio_mux_version_A; ///< LATM syntax version
+ int frame_length_type; ///< 0/1 variable/fixed frame length
+ int frame_length; ///< frame length for fixed frame length
+};
+
+static inline uint32_t latm_get_value(GetBitContext *b)
+{
+ int length = get_bits(b, 2);
+
+ return get_bits_long(b, (length+1)*8);
+}
+
+static int latm_decode_audio_specific_config(struct LATMContext *latmctx,
+ GetBitContext *gb, int asclen)
+{
+ AVCodecContext *avctx = latmctx->aac_ctx.avctx;
+ MPEG4AudioConfig m4ac;
+ AACContext *ac= &latmctx->aac_ctx;
+ int config_start_bit = get_bits_count(gb);
+ int bits_consumed, esize;
+
+ if (config_start_bit % 8) {
+ av_log_missing_feature(latmctx->aac_ctx.avctx, "audio specific "
+ "config not byte aligned.\n", 1);
+ return AVERROR_INVALIDDATA;
+ } else {
+ bits_consumed =
+ decode_audio_specific_config(ac, avctx, &m4ac,
+ gb->buffer + (config_start_bit / 8),
+ get_bits_left(gb) / 8, asclen);
+
+ if (bits_consumed < 0)
+ return AVERROR_INVALIDDATA;
+ ac->m4ac= m4ac;
+
+ esize = (bits_consumed+7) / 8;
+
+ if (avctx->extradata_size <= esize) {
+ av_free(avctx->extradata);
+ avctx->extradata = av_malloc(esize + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!avctx->extradata)
+ return AVERROR(ENOMEM);
+ }
+
+ avctx->extradata_size = esize;
+ memcpy(avctx->extradata, gb->buffer + (config_start_bit/8), esize);
+ memset(avctx->extradata+esize, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
+ skip_bits_long(gb, bits_consumed);
+ }
+
+ return bits_consumed;
+}
+
+static int read_stream_mux_config(struct LATMContext *latmctx,
+ GetBitContext *gb)
+{
+ int ret, audio_mux_version = get_bits(gb, 1);
+
+ latmctx->audio_mux_version_A = 0;
+ if (audio_mux_version)
+ latmctx->audio_mux_version_A = get_bits(gb, 1);
+
+ if (!latmctx->audio_mux_version_A) {
+
+ if (audio_mux_version)
+ latm_get_value(gb); // taraFullness
+
+ skip_bits(gb, 1); // allStreamSameTimeFraming
+ skip_bits(gb, 6); // numSubFrames
+ // numPrograms
+ if (get_bits(gb, 4)) { // numPrograms
+ av_log_missing_feature(latmctx->aac_ctx.avctx,
+ "multiple programs are not supported\n", 1);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ // for each program (which there is only on in DVB)
+
+ // for each layer (which there is only on in DVB)
+ if (get_bits(gb, 3)) { // numLayer
+ av_log_missing_feature(latmctx->aac_ctx.avctx,
+ "multiple layers are not supported\n", 1);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ // for all but first stream: use_same_config = get_bits(gb, 1);
+ if (!audio_mux_version) {
+ if ((ret = latm_decode_audio_specific_config(latmctx, gb, 0)) < 0)
+ return ret;
+ } else {
+ int ascLen = latm_get_value(gb);
+ if ((ret = latm_decode_audio_specific_config(latmctx, gb, ascLen)) < 0)
+ return ret;
+ ascLen -= ret;
+ skip_bits_long(gb, ascLen);
+ }
+
+ latmctx->frame_length_type = get_bits(gb, 3);
+ switch (latmctx->frame_length_type) {
+ case 0:
+ skip_bits(gb, 8); // latmBufferFullness
+ break;
+ case 1:
+ latmctx->frame_length = get_bits(gb, 9);
+ break;
+ case 3:
+ case 4:
+ case 5:
+ skip_bits(gb, 6); // CELP frame length table index
+ break;
+ case 6:
+ case 7:
+ skip_bits(gb, 1); // HVXC frame length table index
+ break;
+ }
+
+ if (get_bits(gb, 1)) { // other data
+ if (audio_mux_version) {
+ latm_get_value(gb); // other_data_bits
+ } else {
+ int esc;
+ do {
+ esc = get_bits(gb, 1);
+ skip_bits(gb, 8);
+ } while (esc);
+ }
+ }
+
+ if (