Commit graph

2754 commits

Author SHA1 Message Date
Sjoerd Simons
b9b5b133fd videorate: Add a max-rate property
In various use-case you want to dynamically change the framerate (e.g.
live streams where the available network bandwidth changes). Doing this
via capsfilters in the pipeline tends to be very cumbersome and racy,
using this property instead makes it very painless.
2011-09-21 11:24:59 +01:00
Sjoerd Simons
ec7ca80c9e videorate: Add more strict caps negotiation
When in drop-only mode we can never provide a framerate that is higher
then the input, so let the caps negotiation reflect this.
2011-09-21 11:24:59 +01:00
Tim-Philipp Müller
f57bbc585d videorate: don't unref event we don't own
http://bugzilla.gnome.org/show_bug.cgi?id=659562
2011-09-20 13:35:55 +01:00
Sebastian Dröge
61c6fcb2cd decodebin2: Only check if this is a discarded type if we have fixed caps
For unfixed caps we will get here again later when the caps are fixed.
2011-09-20 14:06:51 +02:00
Sebastian Dröge
8e114c427a decodebin2: Only call autoplug-continue with fixed caps
With unfixed caps we can't reliably decide if the final caps
are going to be "raw" (e.g. supported by a sink) or not.

We will get here again later when the caps are fixed.
2011-09-20 14:06:42 +02:00
Sebastian Dröge
01d37532b6 subtitleoverlay: Get the target of the video sinkpad, not the target sinkpad in the video setcaps handler 2011-09-19 14:02:00 +02:00
Youness Alaoui
27058c1bc6 decodebin2: Initialize variable correctly
If subdrained isn't initialized to FALSE then a chain might think
that its group is drained when in fact it's not and this can cause
a switch too early or even cause a deadlock.
2011-09-19 12:36:48 +02:00
Edward Hervey
9d2bcb08fe decodebin2: Rewrite EOS-handling code
This is now really threadsafe and improves switching
between different groups.
2011-09-19 12:34:51 +02:00
Sebastian Dröge
936e87cdcf decodebin2: Fix non-prerolling pipelines and not-linked errors if a parser is available but no decoder
Fixes bug #658846.
2011-09-19 11:54:27 +02:00
Sebastian Dröge
b1bb1e9b26 subtitleoverlay: Implement support for switching between raw and non-raw video streams 2011-09-19 11:24:47 +02:00
Alessandro Decina
a330ff0721 playbin2: fix compiler warning
Remove a check for gchar >= 128
2011-09-15 22:05:34 +02:00
Stefan Sauer
b678f6cf69 adder: don't access the event after pushing
Fixes valgrind warnings.
2011-09-15 16:47:26 +02:00
Sebastian Dröge
bd52f00796 Revert "playbin2: autoplug sink if stream is incompatible to the configured one"
This reverts commit b0b4e286c8.

We agreed that the previous (pre-.35) behaviour is broken and a bug and the
current behaviour is correct, deterministic and allows the application to
handle stuff properly while the old behaviour can't be handled properly by
applications and just worked in some applications by luck.

The solution to the problem that was solved by relying on the old, broken
behaviour would be, to make decodebin2/playbin2 more aware of decoders and
improve the autoplugging of decoders by considering the caps supported by the
sink instead of just using something with the highest rank.

See bug #656923.
2011-09-15 14:27:35 +02:00
Josep Torra
b0b4e286c8 playbin2: autoplug sink if stream is incompatible to the configured one
Fixes regression since 0.10.33 where sinks that can cope with non raw
caps or custom caps are not autoplugged if there's a sink configured
with the properties video-sink and audio-sink which cannot handle
the stream. This change checks for compatibility on the configured one
and use it if success. Otherwhise it tries with the found factories.
2011-09-15 09:30:25 +02:00
Josep Torra
8f8ad316ce Revert "playsink: only add text overlay if vido sink also accepts raw caps"
This reverts commit a22faad18a. Instead
of disabling subtitles completelly when video stream have custom caps,
just let the sutbtileoverlay cope with them as now it's able to.
2011-09-14 11:05:45 +02:00
Josep Torra
596c75b541 subtitleoverlay: gracefully handle non raw video streams
Implement handling of non raw video streams by avoiding colorspace
elements and autoplugging a compatible renderer if available. Fallback
to passthrough if no compatible renderer is found.
2011-09-14 11:05:45 +02:00
Tim-Philipp Müller
14a79628a7 playbin2: try to catch malformed URIs
Only log in debug log for now, since the check is a bit
half-hearted, its purpose is mostly to make sure people
use gst_filename_to_uri() or g_filename_to_uri().

https://bugzilla.gnome.org/show_bug.cgi?id=654673
2011-09-13 21:57:10 +01:00
Vincent Penquerc'h
4095551b31 typefind: recognize Asylum modules
Note that there is already a AMF detection for a different
magic, I'm not sure if that's a different format with the
same initials or not. AMF is used for a few different formats
(including video), so...

This fixes playbin2 playing Asylum modules.

https://bugzilla.gnome.org/show_bug.cgi?id=658514
2011-09-09 13:54:45 +02:00
Nicolas Dufresne
25939e0218 subparse: Improve subrip type check regex
This patch prevents timestamp like "1 1:00:00", which would have been seen
as hour 101 by our parser, and allow single digit hour, minute and seconds
as it's already supported by the parser, and also by other implementation
like in mplayer. This fixes bug 657872.

https://bugzilla.gnome.org/show_bug.cgi?id=657872
2011-09-08 14:52:15 +02:00
Sebastian Dröge
5f5d832a3b Revert "decodebin2: Do a subset check before actually using a factory"
This reverts commit 50a88396ae.

See bug #658541.
2011-09-08 13:25:27 +02:00
Sebastian Dröge
9e2ce5bbb5 decodebin2: Make sure to fixate Parser/Converter caps before continuing autoplugging 2011-09-07 16:44:59 +02:00
Josep Torra
a22faad18a playsink: only add text overlay if vido sink also accepts raw caps
Fixes regression, pipeline fails with not negotiated, on media
containing subtitles when decoder/sink with custom caps is used.
2011-09-07 16:08:38 +02:00
Sebastian Dröge
46e26824d4 decodebin2: Intersect the factory caps with the current caps for the capsfilter
Otherwise we'll include many incompatible caps in the capsfilter that
will only slow down negotiation.
2011-09-07 14:20:36 +02:00
Stefan Sauer
abc96efb2a docs: add two mising enum docs 2011-09-07 14:14:02 +02:00
Tim-Philipp Müller
f93748fbd4 decodebin2: fix element factory refcounting
g_value_get_object() does not give us our own ref.

Fixes "Trying to dispose object "flacparse", but it still has a parent "registry0".
You need to let the parent manage the object instead of unreffing the object directly."
and similar warnings.

https://bugzilla.gnome.org/show_bug.cgi?id=658416
2011-09-07 12:34:06 +01:00
Sebastian Dröge
50a88396ae decodebin2: Do a subset check before actually using a factory
This prevents autoplugging if the caps have a non-empty intersection
but are not accepted by the next element's pad.
2011-09-06 14:16:10 +02:00
Sebastian Dröge
c5733632ee subtitleoverlay: Use subset check instead of non-empty-intersection check to check if pads are compatible 2011-09-06 14:04:34 +02:00
Sebastian Dröge
e3530f434b playbin2: Use subset check instead of non-empty-intersection check to check if pads are compatible 2011-09-06 14:03:31 +02:00
Sebastian Dröge
4be8c44b08 decodebin2: Fix memory leak 2011-09-06 13:16:44 +02:00
Sebastian Dröge
20f9d0bec5 decodebin2: Correctly negotiate format for parsers that can convert different stream formats
This is done by adding a capsfilter after every parser/converter that contains
all possible caps supported by downstream elements. A capsfilter is necessary
here because the decoder is only selected after the parser selected a format
and the parser can't know what downstream would support otherwise.
2011-09-06 13:16:44 +02:00
Sebastian Dröge
1df9fa9ee8 playbin2: If a audio/video sink was already selected don't check caps of all other possible sinks 2011-09-06 13:16:44 +02:00
Vincent Penquerc'h
78f50f2d25 videorate: don't take the object lock twice in {set,get}_property
https://bugzilla.gnome.org/show_bug.cgi?id=658294
2011-09-06 09:44:38 +01:00
Thiago Santos
2768ed75e0 encodebin: Select muxer further
Sort muxers based on their caps and ranking before iterating to
find one that fits the profile.

Sorting is done by putting the elements that have a pad template
that can produce the exact caps that is on the profile. For example:
when asking for "video/quicktime, variant=iso", muxers that
have this exact caps on their pad templates will be put first on
the list than ones that have only "video/quicktime".

https://bugzilla.gnome.org/show_bug.cgi?id=651496
2011-09-05 17:48:36 -03:00
Sebastian Dröge
de4fc848fa decodebin2: Actually iterate over the factories instead of only taking the first one 2011-09-05 20:32:42 +02:00
Tim-Philipp Müller
b1c00adf31 Revert "playsink: Try include 'pitch', if no other sink is provided"
This reverts commit 105814e2c7.

The general consensus seems to be that we should revert this for
now. If such behaviour is desired, we should probably enable it
via a flag. And maybe use the scaletempo plugin instead.
2011-09-05 14:44:27 +01:00
Sebastian Dröge
705ca1d55a playsink: Don't leak the videochain ts-offset element
Also don't leak the audiochain ts-offset element if one is
found but the sink doesn't support volume settings.
2011-09-05 12:02:37 +02:00
Sebastian Dröge
89a899fd9d playsink: Use gst_object_unref() instead of g_object_unref() for better debugging 2011-09-05 11:55:59 +02:00
David Schleef
4e38577b30 videoscale: Add modified Lanczos scaling method
Adds a Lanczos-derived scaling method, which is rather slow, but very
high quality.  Adds a few properties that can be used to tune various
scaling properties: sharpness, sharpen, envelope, dither.  Not currently
Orcified, but was designed with that in mind.
2011-09-01 15:16:50 -07:00
David Schleef
924f743981 playback: Add define for colorspace element
Single point of change if you want to switch from ffmpegcolorspace
to colorspace.
2011-09-01 11:41:31 -07:00
Sjoerd Simons
08ac05a06c videorate: fix dynamically changing average period
The average_period_set variable can be accessed in different threads, so
always lock it when reading. Furthermore when switching to averaging
mode we should make sure we don't have cached buffers that aren't used
in that mode. And any modeswitch will cause the latency to change, so we
should post a NewLatency message
2011-08-31 14:13:56 +01:00
Sjoerd Simons
ea46b3c706 videorate: Port to basetransform 2011-08-31 14:13:56 +01:00
Sjoerd Simons
f2438913f9 Correct added versions 2011-08-31 14:13:55 +01:00
Sebastian Dröge
49b301bcd6 playsink: Only unref ts_offset elements if they're not NULL 2011-08-31 14:45:08 +02:00
Sebastian Dröge
425d3ae7bc decodebin2: Keep the chain mutex locked while connecting to the notify::caps signal 2011-08-31 12:40:30 +02:00
Jan Schmidt
105814e2c7 playsink: Try include 'pitch', if no other sink is provided
As a default, try the pipeline 'pitch ! audioconvert ! autoaudiosink'
before trying plain autoaudiosink
2011-08-30 18:21:31 +10:00
David Schleef
a912374342 playback: reference count ts_offset
Apparently this object is being used after it's freed.  This is one
way to fix it, although perhaps not the best way.  Fixes: #656715.
2011-08-25 14:08:34 -07:00
Sebastian Dröge
e9a5d4f8fd playsink{audio,video}convert: Send NEWSEGMENT events to sinkpads instead of pushing them 2011-08-24 14:05:27 +02:00
Edward Hervey
2ee31ccac9 playsink: Reconfigure when pads are added later
Instead of just assuming all pads are created at the same time,
remember which ones are actually new (via ->pending_blocked_pads).

This allows the following use-case to properly work:
* Upstream starts with audio-only
* Only that pad gets data, blocks and a real audio sink is created
* Upstream laters adds a video stream
* A new pad is requested, blocks and reconfiguration kicks in in
  order to add a new real video sink
2011-08-18 13:42:26 +02:00
Vincent Penquerc'h
30236ddfd3 audioresample: fix build without orc
https://bugzilla.gnome.org/show_bug.cgi?id=656781
2011-08-18 11:03:58 +02:00
Vincent Penquerc'h
49ec6899f4 audioresample: fix quality setting being ignored by the resampler state
https://bugzilla.gnome.org/show_bug.cgi?id=636562
2011-08-12 09:55:17 +02:00
Vincent Penquerc'h
746415a6e3 audioresample: use SSE/SSE2 when possible
Compile in the code on i386 and x86_64, and use ORC to determine
when the runtime platform can run the code.

https://bugzilla.gnome.org/show_bug.cgi?id=636562
2011-08-12 09:55:11 +02:00
Vincent Penquerc'h
58fd202b7d audioresample: fix SSE2 building with double precision
The full double implementation was missing.

https://bugzilla.gnome.org/show_bug.cgi?id=636562
2011-08-12 09:53:12 +02:00
Tim-Philipp Müller
1c0fbbce10 subparse: fix runtime warnings when doing position query
Add missing 'break'.
2011-08-10 10:49:38 +01:00
Vincent Penquerc'h
fa3e246866 typefind: bump probability if all frames we found are similar
Similar meaning same layer, same bitrate, and same number of channels

This fixes misdetection of (some MP3 files that have zero padding
between the ID3 tag and the MP3 stream) as H.264 video.

https://bugzilla.gnome.org/show_bug.cgi?id=656018
2011-08-10 11:20:31 +02:00
Vincent Penquerc'h
c2ce145e72 volume: fix sample depth typo
https://bugzilla.gnome.org/show_bug.cgi?id=656022
2011-08-05 13:37:05 +02:00
Sebastian Dröge
5580dd6a4d volume: Update disted ORC files 2011-08-05 13:06:31 +02:00
Thiago Santos
3687b056c4 encodebin: Set queues to silent=true
As encodebin doesn't connect to the queue signals, it can set
queues to silent mode to make queue not emit them.

Check https://bugzilla.gnome.org/show_bug.cgi?id=621299 for
more info on queue's silent property.
2011-08-03 14:14:55 -03:00
Thiago Santos
b263bacc57 encodebin: Fix typo on installing properties
queue buffers and bytes properties have ids swapped, fix it.
2011-08-03 13:41:10 -03:00
Thiago Santos
c874edd089 encodebin: rename flags names
Rename flags names from native-audio/-video to
no-audio/video-conversion to be more explicit on what it does
2011-07-28 11:21:26 -03:00
Stefan Kost
9a26e6c7bc adder: rework pending event handling
Use atomic ops on pending flags. Rename the segment_pending to
new_segment_pending. Set new_segment_pending not when we received seek, but
when we received the first upstream new_segment.
2011-07-26 12:37:11 +02:00
Stefan Kost
a8228b062a adder: more debug logging for events 2011-07-26 12:37:11 +02:00
Edward Hervey
38a6919a7b decodebin2: Allow all EOS to go through if we don't have a next group
Only drop them if the current group isn't drained .. AND there is a
next group to switch to.

Should Fix #655268
2011-07-26 12:33:56 +02:00
Edward Hervey
059db89633 playbin2: Avoid resetting playsink when not needed
When we don't have specific {audio|video|text}-sink properties, don't
set them on playsink when reconfiguring.
If we do that, we end up setting the previous configured sink to
GST_STATE_NULL resulting in any potentially pending push being returned
with GST_FLOW_WRONG_STATE which will cause the upstream elements to
silently stop.

https://bugzilla.gnome.org/show_bug.cgi?id=655279
2011-07-25 18:44:33 +02:00
Edward Hervey
c91928f7a2 decodebin2: Properly handle multi-stream chains
When we have a multi-stream (i.e. audio and video) input and the demuxer
adds/removes pads for a new stream (common in a mpeg-ts stream when the
program stream mapping is updated), the algorithm for EOS handling was
previously wrong (it would only drop the EOS of the *last* pad but would
let the EOS on the other pads go through).

The logic has only been changed a tiny bit for EOS handling resulting in:
* If there is no next group, let the EOS go through
* If there is a next group, but not all pads are drained in the active
  group, drop the EOS event
* If there is a next group and all pads are drained, then the ghostpads
  will be removed and the EOS event will be dropped automatically.
2011-07-25 10:45:36 +02:00
Tim-Philipp Müller
9edbc92a27 decodebin: don't plug the same parser multiple times in a row
This allows us to make parsers accept both parsed and unparsed input
without decodebin plugging them in a loop until things blow up, ie.
without affecting applications that still use the old playbin or the
old decodebin.

(Making parsers accept parsed input is useful for later when we want
to use parsers to convert the stream-format into something the decoder
can handle. It's also much more convenient for application authors
who can plug parsers unconditionally in transcoding pipelines, for
example).
2011-07-15 16:14:11 +01:00
Piotr Fusik
b27d2469bd typefind: fixed detection of audio/x-sap
Fixes: #654295.

Signed-off-by: David Schleef <ds@schleef.org>
2011-07-09 16:19:48 -07:00
Luis de Bethencourt
bf816fe816 encodebin: fix compiler warning
cspace and cspace2 may run uninitialized.
2011-06-30 19:57:22 +01:00
Robert Swain
7ad1ba6fba encodebin: Add flags to disable conversion elements
Add a flags property and two flags to allow one to disable the
conversion elements within encodebin. Doing so insists that the
uncompressed input to encodebin for the appropriate stream type is
sufficient to meet the caps requirements of the encoders, muxers and
encodebin target.

This is mostly beneficial to bypass slow caps negotiations in the
conversion elements.
2011-06-30 00:59:18 +02:00
Robert Swain
dc79c42484 streamsplitter: Fix getcaps src pad caps merge
Caps returned from gst_pad_peer_get_caps_reffed () may not be writable.
If they are not is should cause an assertion in gst_caps_merge (),
however, sometimes assertions are disabled in binary builds of -base and
it's safer to just be sure the caps are writable. Also, check that the
reffed caps pointer is not NULL.
2011-06-29 11:57:52 +02:00
Philip Jägenstedt
f3e65f1c93 typefind: NULL check in degas_type_find
The length check isn't sufficient, an source might
report the correct length, but then still fail to
read the requested number of bytes for some reason.

https://bugzilla.gnome.org/show_bug.cgi?id=652642
2011-06-26 23:31:33 +01:00
David Schleef
4db89c82bb convert M_PI to G_PI, for msvc 2011-06-10 23:56:34 -07:00
Tim-Philipp Müller
c692191c33 GST_PLUGINS_BASE_LIBS is not defined in -base. 2011-06-08 12:21:43 +01:00
David Schleef
836081abee adder: Work around changes in g_atomic API
See #651514 for details.
2011-06-04 13:36:55 -07:00
Tim-Philipp Müller
d10a7b439b typefinding: add typefinder for WAP WBMP bitmaps
https://bugzilla.gnome.org/show_bug.cgi?id=651294
2011-06-02 14:36:06 +01:00
Sebastian Dröge
5c97aa2e5c playsink: Fix deadlock in the audio/video converter bins when linking fails 2011-06-02 11:54:35 +02:00
Sebastian Dröge
8f967e9e70 volume: Fix handling of volume>=4.0 for 8 and 16 bit integer formats
Also add a unit test for this. Previously volumes bigger than 4.0
would have resulted in overflows in the fixed point processing.

Fixes bug #649642.
2011-05-31 11:07:11 +02:00
Sebastian Dröge
216258fbc2 playbin2: Let the input-selectors sync all streams to the running time
This is especially needed when switching between a non-sparse and sparse
video stream, see bug #537382. It also lowers the time needed for switching
between streams a bit.
2011-05-26 11:41:50 +02:00
Stefan Kost
5cd0e0f666 audiotestsrc: add blue and violet noise by using spectral inversion
Add blue and violet noise by spectral inversion of pink and red noise.
Fixes #649969
2011-05-26 00:18:55 +03:00
Stefan Kost
1cf831e74e audiotestsrc: add red (brownian) noise generator
Add another noise generator which produces a quite dark noise color.

Fixes parts of #649969.
2011-05-25 23:43:56 +03:00
Stefan Kost
1916eecc30 volume: use a flag for 'mute' using the controller
Previously we checked mute_csource to determine wheter we need to premultiply
volumes and mute values. That fails as we unrefs mute_csource and set it to
NULL after. Use an extra flag instead.
2011-05-25 14:28:18 +03:00
Sebastian Dröge
c867f677c0 subparse: Try to typefind even if conversion to UTF8 failed
Fixes bug #600043.
2011-05-23 16:05:35 +02:00
Sebastian Dröge
2c7cdbc2ca subparse: Compile the typefind regex with optimization to speed up matching 2011-05-23 16:05:35 +02:00
Sebastian Dröge
3dc4987138 subparse: Interprete typefind strings passed to GRegex as raw bytes instead of valid UTF8 2011-05-23 16:05:35 +02:00
Stefan Kost
762bb236fa docs: fixup appsrc/sink api docs 2011-05-23 15:02:27 +03:00
Stefan Kost
f514be993c audioconvert: cleanup helper code
make_lossless_changes() returns the same structure that we're passing (probably
to enable chaining). Instead of reusing s and making it point to s2 as well,
keep using s2. Drop the assignment which in the 2nd case is a dead one anyway.
2011-05-19 23:41:08 +03:00
Thiago Santos
b5fb542386 encodebin: Autoplug formatters
Autoplug formatters for streams if a formatter with secondary or
higher rank is found. Formatters are autoplugged when there is no
muxer or when the muxer doesn't implement the tagsetter interface.

Currently only the first formatter found is plugged, this might
help in lots of cases, but it doesn't solve the
'lamemp3 ! xingmux ! id3mux'
case.

https://bugzilla.gnome.org/show_bug.cgi?id=649841
2011-05-19 08:35:46 -03:00
Thiago Santos
0060900d68 encodebin: fix typos 2011-05-19 08:30:03 -03:00
Mark Nauwelaerts
eba4a948fb videorate: optionally ensure maximum average output frame rate
See #628764.
2011-05-16 12:46:00 +02:00
Alexey Fisher
1e09272024 videorate: optionally only drop frames to ensure maximum frame rate
This adds option to arrange for maximal allowed variable frame rate.

Fixes #628764.
2011-05-16 12:45:47 +02:00
Mark Nauwelaerts
4ba6acdba5 uridecodebin: use bitrate to configure streaming buffer-duration default case
In particular, in audio only cases whose (estimated) metadata provides bitrate
information, the buffer-size based on such bitrate (and buffer-duration)
will be much more reasonable than queue2 default buffer-size.
2011-05-16 12:44:52 +02:00
Mark Nauwelaerts
8480b1ef1d uridecodebin: remove some dead code
... which was dead as pads were never added to the list, and need not be added,
since removing them is handled by a pad callback.
2011-05-16 12:44:50 +02:00
Thiago Santos
fd486588ce encodebin: Check for missing converters
Adds checks for missing video and audio converter elements
2011-05-15 13:02:39 -03:00
Andoni Morales Alastruey
dd36e4cd0e decodebin2: fix preroll for streams at low bitrates
For streams at low bitrates we need to set a limit in time because the limit
in bytes might not reached too late, sometimes more than 30 seconds.
This limit can only be set if upstream is seekable (see #584104)
Closes #647769
2011-05-14 11:42:33 +02:00
Sebastian Dröge
9337a293e1 playsink: Use new ghostpad/proxypad API to get the internal pad 2011-05-14 11:42:33 +02:00
Sebastian Dröge
9b6e1952a4 playsink: Use new ghostpad/proxypad API 2011-05-14 11:42:33 +02:00
Sebastian Dröge
2f8467d682 playsink: Add audio and video converter convenience bins
These reconfigure based on the caps and plugin in converters if
necessary. This also makes switching between compressed and raw
streams work flawlessly without loosing the states of any element
somewhere or having running time problems.
2011-05-14 11:42:32 +02:00
Sebastian Dröge
105da803ad playbin2/playsink: Decide if A/V caps are raw only inside playsink
Before playbin2 would use different selectors for raw audio and
compressed audio (and the same for video) and used different
pads from playsink. This made the involved logic much more
complex and was not implemented completely in playsink, which
made it impossible to support files with a compressed and
uncompressed stream that is support by the sink.

playbin2 handles raw/non-raw streams the same now and the
decision is left to playsink, which now can also handle
caps changes from raw to non-raw and the other way around.

Fixes bug #632788.
2011-05-14 11:42:32 +02:00
Sebastian Dröge
45bf51dcdf subtitleoverlay: Use new, public ghostpad functions 2011-05-14 11:42:32 +02:00
Tim-Philipp Müller
288f8babd1 gst: update orc-generated disted C backup code to orc 0.4.14 2011-04-30 17:21:28 +01:00
David Schleef
fc31f355ea videoscale: Fix off-by-one error in previous commit
Fix for 7c0b702e.  It helps to get your j+1's right.
2011-04-24 18:46:52 -07:00