[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 07/10] source/{av, ff}: probe harder for audio in weird container
From: |
Eric Wong |
Subject: |
[PATCH 07/10] source/{av, ff}: probe harder for audio in weird containers |
Date: |
Sun, 1 Sep 2013 01:22:07 +0000 |
Some containers (e.g. large VOBs) are not easily probed and require
additional options for avprobe/ffprobe to find audio streams. We do
this by looping and increasing the duration/size of the probe to
find new audio streams.
This seems to work reasonably well for some DVD rips I have until
seeking is required. This breaks if the seek point (including seeks
for source effects) exceeds the avprobe/ffprobe -analyzeduration.
Anyways, I recommend extracting the audio stream (without
transcoding) out of the VOB container as the best way to go.
Something like:
avconv -analyzeduration 2G -probesize 2G \
-i input.vob -vn -sn -c:a copy -map 0:$STREAM_NR output.ext
---
lib/dtas/source/av.rb | 2 +-
lib/dtas/source/av_ff_common.rb | 82 +++++++++++++++++++++++++++++++----------
lib/dtas/source/ff.rb | 2 +-
3 files changed, 64 insertions(+), 22 deletions(-)
diff --git a/lib/dtas/source/av.rb b/lib/dtas/source/av.rb
index d44b1a9..e03c89d 100644
--- a/lib/dtas/source/av.rb
+++ b/lib/dtas/source/av.rb
@@ -9,7 +9,7 @@ class DTAS::Source::Av # :nodoc:
AV_DEFAULTS = COMMAND_DEFAULTS.merge(
"command" =>
- 'avconv -v error $SSPOS -i "$INFILE" $AMAP -f sox - |' \
+ 'avconv -v error $SSPOS $PROBE -i "$INFILE" $AMAP -f sox - |' \
'sox -p $SOXFMT - $RGFX',
# this is above ffmpeg because this av is the Debian default and
diff --git a/lib/dtas/source/av_ff_common.rb b/lib/dtas/source/av_ff_common.rb
index 2ae8d69..e513217 100644
--- a/lib/dtas/source/av_ff_common.rb
+++ b/lib/dtas/source/av_ff_common.rb
@@ -25,39 +25,80 @@ module DTAS::Source::AvFfCommon # :nodoc:
rv
end
+ def __parse_astream(cmd, stream)
+ stream =~ /^codec_type=audio$/ or return
+ as = AStream.new
+ index = nil
+ stream =~ /^index=(\d+)\s*$/nm and index = $1.to_i
+ stream =~ /^duration=([\d\.]+)\s*$/nm and as.duration = $1.to_f
+ stream =~ /^channels=(\d)\s*$/nm and as.channels = $1.to_i
+ stream =~ /^sample_rate=([\d\.]+)\s*$/nm and as.rate = $1.to_i
+ index or raise "BUG: no audio index from #{xs(cmd)}"
+ yield(index, as)
+ end
+
+ def probe_ok?(status, err_str)
+ return false if Process::Status === status
+ return false if err_str =~ /Unable to find a suitable output format for/
+ true
+ end
+
def av_ff_ok?
@duration = nil
@format = DTAS::Format.new
@format.bits = 32 # always, since we still use the "sox" format
@comments = {}
@astreams = []
- cmd = %W(address@hidden -show_streams -show_format address@hidden)
- err = ""
- s = qx(@env, cmd, err_str: err, no_raise: true)
- return false if Process::Status === s
- return false if err =~ /Unable to find a suitable output format for/
- s.scan(%r{^\[STREAM\]\n(.*?)\n\[/STREAM\]\n}mn) do |_|
- stream = $1
- if stream =~ /^codec_type=audio$/
- as = AStream.new
- index = nil
- stream =~ /^index=(\d+)\s*$/nm and index = $1.to_i
- stream =~ /^duration=([\d\.]+)\s*$/nm and as.duration = $1.to_f
- stream =~ /^channels=(\d)\s*$/nm and as.channels = $1.to_i
- stream =~ /^sample_rate=([\d\.]+)\s*$/nm and as.rate = $1.to_i
- index or raise "BUG: no audio index from #{xs(cmd)}"
-
- # some streams have zero channels
- @astreams[index] = as if as.channels > 0 && as.rate > 0
+
+ # needed for VOB and other formats which scatter metadata all over the
+ # place and
+ @probe_harder = nil
+ incomplete = []
+ prev_cmd = []
+
+ begin # loop
+ cmd = %W(address@hidden)
+
+ # using the max known duration as a analyzeduration seems to work
+ # for the few VOBs I've tested, but seeking is still broken.
+ max_duration = 0
+ incomplete.each do |as|
+ as && as.duration or next
+ max_duration = as.duration if as.duration > max_duration
end
- end
+ if max_duration > 0
+ usec = max_duration.round * 1000000
+ usec = "2G" if usec >= 0x7fffffff # limited to INT_MAX :<
+ @probe_harder = %W(-analyzeduration #{usec} -probesize 2G)
+ cmd.concat(@probe_harder)
+ end
+ cmd.concat(%W(-show_streams -show_format address@hidden))
+ break if cmd == prev_cmd
+
+ err = ""
+ s = qx(@env, cmd, err_str: err, no_raise: true)
+ return false unless probe_ok?(s, err)
+ s.scan(%r{^\[STREAM\]\n(.*?)\n\[/STREAM\]\n}mn) do |_|
+ __parse_astream(cmd, $1) do |index, as|
+ # incomplete streams may have zero channels
+ if as.channels > 0 && as.rate > 0
+ @astreams[index] = as
+ incomplete[index] = nil
+ else
+ incomplete[index] = as
+ end
+ end
+ end
+ prev_cmd = cmd
+ end while incomplete.compact[0]
+
s.scan(%r{^\[FORMAT\]\n(.*?)\n\[/FORMAT\]\n}m) do |_|
f = $1
f =~ /^duration=([\d\.]+)\s*$/nm and @duration = $1.to_f
# TODO: multi-line/multi-value/repeated tags
f.gsub!(/^TAG:([^=]+)=(.*)$/ni) { |_| @comments[$1.upcase] = $2 }
end
- ! @astreams.empty?
+ ! @astreams.compact.empty?
end
def sspos(offset)
@@ -105,6 +146,7 @@ module DTAS::Source::AvFfCommon # :nodoc:
e = @env.merge!(player_format.to_env)
+ e["PROBE"] = @probe_harder ? @probe_harder.join(' ') : nil
# make sure these are visible to the source command...
e["INFILE"] = @infile
e["AMAP"] = amap
diff --git a/lib/dtas/source/ff.rb b/lib/dtas/source/ff.rb
index fa4bbf7..9f1cffc 100644
--- a/lib/dtas/source/ff.rb
+++ b/lib/dtas/source/ff.rb
@@ -11,7 +11,7 @@ class DTAS::Source::Ff # :nodoc:
FF_DEFAULTS = COMMAND_DEFAULTS.merge(
"command" =>
- 'ffmpeg -v error $SSPOS -i "$INFILE" $AMAP -f sox - |' \
+ 'ffmpeg -v error $SSPOS $PROBE -i "$INFILE" $AMAP -f sox - |' \
'sox -p $SOXFMT - $RGFX',
# I haven't tested this much since av is in Debian stable and ff is not
--
1.8.4
- [PATCH 0/10] misc updates to master, Eric Wong, 2013/08/31
- [PATCH 02/10] GNUmakefile: combine with pkg.mk, Eric Wong, 2013/08/31
- [PATCH 08/10] doc: reorganize sections around dtas-player, Eric Wong, 2013/08/31
- [PATCH 10/10] doc: add contact info to all documentation, Eric Wong, 2013/08/31
- [PATCH 09/10] doc: sink_examples: reference dtas-xdelay and friends, Eric Wong, 2013/08/31
- [PATCH 04/10] Rakefile: wrap long line, Eric Wong, 2013/08/31
- [PATCH 07/10] source/{av, ff}: probe harder for audio in weird containers,
Eric Wong <=
- [PATCH 03/10] Rakefile: additional pointer to git-set-file-times, Eric Wong, 2013/08/31
- [PATCH 05/10] dtas-sourcedit: allow loading YAML from stdin, Eric Wong, 2013/08/31
- [PATCH 06/10] test_source_av: fix test to actually run, Eric Wong, 2013/08/31
- [PATCH 01/10] disclaimer: disambiguate between dtas/$PROGNAME, Eric Wong, 2013/08/31