See also: IRC log
<vivien> Slides (google docs)
HTA: the aim of the
group is now to get WebRTC 1.0 out of the door, get it to CR
state as soon as we can
... so that we can say we have completed this task
... we have other
documents that we will talk about after lunch today that also
need to be completed
... the media capture stuff
Stefan: High level
agenda: we're gonna start this morning by hammering issues
about peer connection
... this afternoon we
will focus on media capture documents; mainly getUserMedia, but
also depth and audio output
... Friday, morning will focus on sender/receiver, dtmf and stats
... In the afternoon,
we will discuss the certificate and IdP stuff with EKR joining
us at 1pm sharp
... then ICE, test suite and summary
Issue 782 pc.createOffer(); pc.addTrack(track); should not include track
AdamB: the crux of this is to
make it consistent what ends up in an offer
... there is a pull request that proposes a solution for
this
... right now we have split up createOffer step in a set of
synchronous steps and a set of queued steps
... if we bundle the set of tracks in the synchronous steps, we
get the agreed upon effect
Cullen: that behavior seems surprising to me
JIB: we've had users confused
that tracks added after createOffer were included in the
negotiation
... the main thing is to have it predictable
... even if that particular pattern is not something that is
particularly expected to be used
Cullen: I still think this is a surprising behavior for an asynchronous operation
JIB: now that we have that proposal, I think this is predictable
AdamR: people shouldn't do this; this works, I don't think it's worth discussing it so much
Cullen: but then we should do it for all our async calls
PeterT: I'm not sure this is worth all this complexity
AdamR: what does our implementation do at the moment?
JIB: it's complicated
... right now we always queue createOffer
... and we have bugs
... it may depends on whether this is the first session or
not
DanB: what would be a dev expect when writing such a code?
Dom: this is an anti-pattern of programming; the only thing we need is predictable outcome
AdamB: if addTrack was promise-based, we wouldn't have that issue
PeterT: the fundamental problem is for addTrack that returns synchronously
AdamB: one part of the question
is whether there are other methods that would need this
handling
... I don't think there are other places than
createOffer/Answer
JIB: I like this overall, but am
concerned when the queue is empty
... and PeterT's concern is relevant
PeterT: even if we agree we want
this behavior, I've commented on the Pull Request; we can
improve the description of the behavior
... I'm still not sure this is worth the effort though
JIB: I think we need: syncrhonous
steps, queued synchronous steps, and then queued asynchronous
steps
... I think we can massage the PR to do that
HTA: JIB, will you write the test case to reflect this?
JIB: I will
... and work with AdamB to update the PR
PeterT: whatever change we make, createAnswer needs to be consistent
HTA: it seems like everyone is willing to live with this behavior, given that we need consistent behavior
PeterT: I'm not sure I'm willing to live with adding complexity to the spec
HTA: but what's the alternative that achieves consistant behavior?
PeterT: what about the other
direction?
... when the second-added track gets added to the offer
Dom: not clear that this is less complex
JIB: I think it also much more likely to be race-y
DanB: let's maybe get these people to work together and revisit it tomorrow
Issue 787 Integrate RTCRtpTransceiver into set local/remote steps
AdamB: we need to integrate the
transceivers in createA/O and setL/RD
... JSEP has already pretty good text on this aspect
... I've written up a proposal to use a provisional mid
... which gets discarded if a transceiver gets it from the
remote side
PeterT: why do we need a provisional mid?
AdamB: if we do addTrack and then createOffer
PeterT: the mid is generated but
not shown in the object until setL/RD
... this feels like this is something that only needs to be
specified in JSEP
<vivien> [ FYI, The WebEx session is now being recorded ]
AdamB: when setLD has succeeded,
we need a mid — so the idea is that we get it from JSEP
... I'll work on a PR in that direction
Bernard: we just need to refer to the right JSEP section
AdamB: so the PR is essentially a reference to JSEP that explains that it defines how the mid gets defined
Issue 645 public negotiation-needed flag as readonly
AdamB: we got the request to
expose the negotiation-needed flag as a public read only
attribute
... I'm not sure I'm convinced by the arguments
JIB: we do expose other states for which we have events
AdamB: but these other states are
more than just boolean
... my proposal is to do nothing
JIB: if you add tracks and data channels not in the same event loop, you might have a race condition with the negotiated-needed event
PeterT: if we were to have this, we need to be careful with when the state is set
JIB: but that's we already do with other events
Dom: feels to me that this is a new feature that doesn't solve critical use cases; and we don't do new features at this point
AdamB: are we clear on whether we send negotiation needed every time or just when the state changes?
AdamR: the spec is clear - it's only when it changes
[more discussion that this may not be as clear]
HTA: a test case would help determine the negotiation needed behavior
AdamB: I can take a stab at it
JIB: will help
Dom: so the conclusion is "no" to 645 but we may need to clarify the negotiation needed behavior
Issue 746 Need to specify what happens if `createDataChannel` is called with an invalid ID
Taylor: there are a number of cases where you can have an invalid id for the data channel
[looking at example on slide 13]
Taylor: My proposal is to indicate the error in both cases with the onerror event
JIB: the 65535 case is always an error
PeterT: we need a way to signal the case when we gave you a data channel but don't have any id left to associate with it
Cullen: onerror seems pretty reasonable
HTA: do we need to discuss what to put as error?
Dom: we'll find something in WebIDL
Taylor: do we need to?
Dom: we need to have a defined name
Issue 727 removeTrack: throw exception if sender is not in connection's set of senders
Taylor: the proposal here is to throw an exception when trying to remove a sender from the wrong peer connection object
Cullen: this sounds reasonable
JIB: wouldn't be hard to implement either
[consensus we should do this]
Stefan: will you also write the test case, taylor?
Taylor: sure
Issue 526 NetworkError event is not defined and might not be needed
AdamB: we have this NetworkError
in the spec that we don't define and that we fire when the
transport of a data channel is closed with a failure
... that behavior is borrowed from Web Sockets; they only fire
a simple error event, and then a close event with more info
<adamR> adambe: https://www.w3.org/TR/dom/#error-names-0
Cullen: the underlying issue is that we have lots of errors where we don't give information about the reason errors
AdamB: we brought this to the
WebIDL meeting yesterday
... and they recognized the issue and said they would fix
it
Cullen: 50% of our errors need more information, and standardized information
Bernard: there are lots of stuff missing
<adamR> adambe: Rather, https://www.w3.org/TR/WebIDL-1/#idl-DOMException-error-names
HTA: the WebIDL model is that errors are simple events
JIB: browsers don't behave the same in error reporting already e.g. on the error stack
Cullen: are you really proposing we don't standardize error reporting?
AdamB: in this specific case, the problem arises from our difference with Web Sockets - they have a close event with a message
JIB: in general, it seems like we should not diverge from Web Sockets
AdamR: FWIW, there is "NetworkError" in WebIDL
RESOLUTION: we will change our close event to match with Web Sockets
HTA: right now, we're not
planning to do work on the bag of errors issue?
... the WebIDL folks indicated they wanted to bring it to
EcmaScript, which may take a lot of time
Cullen: I think we need to discuss this in more depth
<jesup> The room seems to have hung up....
<jesup> fluffy: ^
<thp> It was pretty in-audible anyhow.
<jesup> Weren't they still in coffee break?
<fluffy> Back from coffee break in 5 min
<vivien> jesup, you are right
<vivien> rejoining now
<vivien> jesup, we are back (even if still in break)
jib: there is this new thing called permission specs
it started as an API, but it evolved into that. Query() to read states for permissions.
jib: prompt / granted / denied
are the return vlues
... that control access to the camera / mic
... separate to that we have the permission to use the
algorithm which return only granted or denied
... is the permission is set to prompt (default) you have to
ask the user ,otherwise, you return whatever the value is
... the UA may update the value. The permission specs is not
completely explicit on the HOW, and that s because each browser
can behave slightly differently (that explains the MAY)
... the behavior between HTTP and HTTPS is explicated in the
spec, and i won trepeat it here, but there are some
flexibility
... the impact is that, it messes up our language a little
bit.
... we used to have temporary permission and stored
permissions.
... some users requested that the UA gives visibility to those
stored values [just like cookies]
... now we have three different permission: per use, per realm,
and persistent per origin
... the last t wo are HTTPS only
... any question on that ?
cullen: per realm means per refresh kind of thing?
jib: yes. Permission are persistent until the end of the page. It is already defined in the permission Spec.
stefan: the permission spec also introduce the "settings" part
dom: why per realm is only for https?
jib: permission spec try to
standardize that in explaining what the UA can / cannot do. UA
can do whatever it wants as long as it fits the user intend
(and that is not defined anywhere). It cannot however use any
info ration over http.
... since http is intrinsically insecure.
jib: next slide
... issues to resolve. long threaded
jib: #387: the spec has a privacy
problem.
... discussion on freedom of implementation, while behavior
(ask the user) is standardized.
Issue #389 Camera light and "disabled" tracks
jib: one way to address this
would be to implement the per-use permission rule.
... we should at least revisit our intend.
... that was only discussed in washington DC in 2014
<hta1> s/only// (we discussed it at many other times)
jib: discussing visual indicators in the UA, with screenshots from chrome
cullen: i assume the desire behavior would be: if I pause video, the red indicator on the tab would stay because i m still getting audio, but the cam led would go off.
<thp> Does this cover the case that a site has a 1000:1 duct cycle and takes snapshots every 10 mins?
harald: the problem is, the cam
led is not under the control of the software, but the hardware.
Nowadays, the only way to turn the cam led off one need to
release the camera hardware (capturer) all together.
... eventually, the cam / driver might takes time, or even keep
the light on.
cullen: we could make the cam maker do the right thing ....
jib: the point here was to provide feedback to user.
cullen: yes, i was just trying to define the desirable behavior of camera
jib: ok, let s see next
slide
... #389 allow "on-air" cam light off on mute/disabled
... short of physically unplugging camera,
vivien: does this happen to video only, or audio as well ?
jib: it applies to both, as far as the tab indicator is concerned, but not for the led.
burn: so we keep the tab indicator (red dot) on, if *anything* is on (audio and video)
cullen: there is a privacy concern, even for computers that don't have cam led.
harald: we should add some wording about this.
jib: for the indicator itself, i think we should have as strong a language than we have for security prompt (since it is under our control, unlike cam led)
dom: I agree with the purpose and privacy guarantees we want to get; I'm not sure we can enforce them since showing indicators can be difficult; think of limited mobile screens, or apps in full screen mode
dan: we might not speak about "indicator" but ways of letting the user know wether: it is possible or not, it is happening or not.
#387/389 make indicator a must -
cullen: do we still have text about the indicator staying on for some time, even if the cam was only on for a small amount a time.
jib: good, I think we should definitely do that (leave the indicator on).
adamB: do we need extra language in the specs for that?
harald: we should mandate the tracking of the 2 states (on air / accessible), and strongly encourage make them "visible" to the user
DanB: we could go even further and mandate making the changes to these states visible to the user
Dom: I like that
jib: next slide
DanB: I'll work with JIB on that
Issue #350 New permission definitions are wrong
jib: #350 language ok, one behavioral change
jib: no reprompt in GUM for sources already live on stage
jib: quite frankly, since we are
using the permission spec, apart from http, if you have
indicator, the UA can do whatever you want with respect to
prompts
... we exchanged strong prompt policy for strong indicator
policy
cullen: I'd like someone to explain to me why it is a good thing.
harald: think about a page that
would take a snapshot (authorized) and then 4 hours later
(using the permission given before) switch it back on and do
something evil.
... now, we have indicators to show the use and the CAPACITY of
using it (even if it s not in use).
cullen: ok, so that s only an HTTP problem (since in HTTPS the permission are stored).
harald: if there is no indication of capacity, we need to prompt.
cullen: then, going back to that use case, if we stop using the cam, then capacity is also lost.
jib: I should clarify that the
query() interface behave differently in chrome and FF today.
after a successful call to GUM, a call to query() would still
return "prompt" in FF, to show it's a one-use media
stream.
... <how about permission goes away with garbage
collection>
... i think the HTTP requirement comes from IETF, so we (w3c)
cannot modify it right now.
dom: so .... what was the conclusion here?
discussion jib/adamb/cullen/dom on a summary
cullen: the specs should say very
clearly how long the permission lasts in any case. I do not
think that http or https is so different, you just do not
access storage if over http, but the information might be
stored.
... i am more worried about the maximum amount of time the UA
stores it.
jib: we have 3 access polices now.
cullen: i don't think we need the per-realm one, we do not have use case for it.
jib: edge does it like that
shinjun: one use case is to
attach to a user profile.
... second use case is when you are on a web site, just
finished a call, and a second call comes in, you don t want to
be prompted again, bad UX
dom: that s fine, but what is not right is to require to prompt over HTTP
harald: if we are clear that accessibility device indicator is protection enough, then we should be done?
jib: we should allow some browser to implement stronger privacy policies.
cullen: we just need to be very clear about the intend, and about the length of permission. There are now 2 use cases, one from shinjun and one from harald.
shinjun: ........ (not understandable)
jib/dom: can you rephrase ?
shinjun: we spoke about stronger indicators: on-air (for usage) and another one for permission.capacity
jib: if i understand correctly, even if we have strong indicators, we still need to have strong security.
danB: you need to be sure the user understand what the indicator mean, in term of security
jib: true, and the language about that that was in our spec, is now in a separate document.
cullen: if the permission spec would apply, then permission would go away as soon as we stop using it.
jib: HTTP is simple: nothing than per-use is allowed.
harald: I think we are circling
on that one.
... you only need, really, two variable, one showing if the
camera is in use or not, one showing wether you have permission
to use the cam or not.
jin: oh, i m very clear about this.
cullen: speaking about it it s not clear, but i want to believe that once written it will become clear for the rest of us.
danb: i know how to deal with that. jib and I will take care of it.
stefan: can you do it by tomorrow? it s more efficient to deal with it while we are all here.
danB.
harald: last 1~2 slides. let's do it and go to lunch
Issue #380 Remove redundant list-devices permission
jib: #380 device labels +
devicechange and stop()
... firing the ondevicechange on all tabs using the hardware
was not great.
... labels: if you had permissions, you could see the labels,
otherwise you would shave an empty string.
... if permissions were revoked while you were using the cam,
you keep the label for as long as you use it.
... we propose to have separate device info permission weaker
than GUM permission
<dom> (bikeshedding - "device-info" probably ought to be "usermedia-info" or "usermedia-device-info")
all: we might need an UI in the UA for that ?
dom: is there any AI on this?
DanB: is it true that the only way to have DeviceInfo "granted" is when at one point GUM was also "granted"
jib: as it is today: yes, but the
UA can overrule this.
... we could you have in the future one browser that always
show the labels.
danb: what is the conlusion here?
harald: do It!
danb: do ..... what?
dom: what I find confusing is that by using "weaker than" as a concept, we're putting ourselves in a corner that didn't exist before
ptatcher: there is a lot to explain to the user before he can understand all that.
jib: exposing all that to the user is wrong in the first place.
danb: per use for GUM and per-realm permission for deviceinfo is OK
dom: we might need additional info
jib: yes, we might want that.
ptatcher: we might want to prevent user to get labels, but still provide audio access.
danB: the UA needs to have
perfect clarity of the permission you are asking it. The
consequence is that you cannot ask for one specific cam, and
get permission for more than that.
... people have concerns, and are willing to see a text wording
the proposal, but that s the best we can achieve, here,
now.
jib: list what we agree on
... <proposal 1: opposed by all>
cullen: use case which drove this: the cam was per-use, we are beyond that use, but in the same realm, and we want the deviceinfo to be NOT denied, even though GUM permission would be "prompt" or "denied" (NOT "granted")
<hta1> Lunchtime. We will be back in 1 hour (1:30 local time).
<ningxinhu> https://w3c.github.io/mediacapture-depth/
<ningxinhu> https://github.com/w3c/mediacapture-depth/issues
ningxinhu: Give some info about
implementation feedback and demos
... implementors would like to explicitly define depth
map
... depth value is 16 bit integer
<jesup> Remote can't hear the person speaking, if they can be closer to the mic we might have a chance
ningxinhu: now we can drop the
conversion algorithm
... depth value is distance from point to camera
jib: we're not talking about the depth constraint now, are we?
ningxinhu: no. Depth value in
depth map
... other update is changes to video element
... how to render the depth screen
... we want to leave on-screen rendering to implementations
dom: to clarify, this is about
default rendering in a video element
... video is not the most interesting usage of depth
streams
<ningxinhu> https://github.com/w3c/mediacapture-depth/issues/131
ningxinhu: implementors have
suggested a new image data type for depth
... issue 131
<ningxinhu> https://codereview.chromium.org/2121043002/
fluffy: it's seems weird to
choose the red channel
... so it's actually a single channel image
<ningxinhu> https://jsfiddle.net/astojilj/wq1kwu0t/
ningxinhu: (is showing a
demo)
... use can you js to track your hand
... with the joints
stefanh: regarding
implementations, you mention chromium
... you mention a v2, how far are you from CR for V1?
ningxinhu: we need to reach
consensus on two issues
... canvas stuff and Web GL
dom: why isn't the webgl stuff on the issues list?
ningxinhu: implementors don't want to put hard requirements on the spec
fluffy: devs would like to have near and far values
ningxinhu: we have that in v1
stefan: what about tests
ningxinhu: I need to check that
dom: have we gone through wide review?
chairs: no, not yet
dom: we should do that soon
... we can talk about the processs
burn: is presenting
... in the mcap doc there's a select setting algorithm
Issue #394 Browser's ability to dynamically change settings mistakenly removed
burn: mistake to only execute
algorithm at gum() or applySettings()
... this was a mistake
... (talks about constraints example in slides)
... (issue 394)
burn: example deals with a
setting that becomes impossible for the browser to keep
... do we have agreement that it should work as described in
slides?
... people are agreeing
... I will make a PR
... yay :)
peter: can't the UA do re-selection at any time??
burn: you can do re-selection
unless we don't end up in a overconstrained case
... goal is to give UA freedom, without violating script
wishes
DrAlexG: I'm going to talk about
the status of the test suite for Media Capture and
Streams
... currently gum and webrtc specs have the most advanced test
suites
dom: (explains conditions for
CR)
... almost impossible to get out of CR without reasonable
tests
DrAlexG: how much can two browsers share and still be interpreted as two separate implementations?
dom: they need to be "different enough"
fluffy: the point is: we're the
specs good enough for two implementations to be produced
... a lot of code shared between two of the implementations
dom: the director will not be diving into the implementations
jesup: regarding cullens
comment
... not of code is shared at the DOM level
... more at lower level
DrAlexG: question of interop different between gum and webrtc docs
burn: this is about testing the spec, not immplementations
peter: what about referenced specs
dom: up to this group to
decide
... there's no end to the testing you can do
DrAlexG: let's talk about this
tomorrow
... (talking about test coverage slide)
jib: are you adding tests that aren't working in any browser?
DrAlexG: yes
... there are things that can be easy fixed
... for example: MediaStreamTrack.getTracks
... and new things related to the constrainable pattern
jib: how do you determine test coverage
DrAlexG: manually!
... some parts of the spec is hard to test
... for example camera behavior
fluffy: people have made fake cameras for testing
DrAlexG: hard to test tricky
cases
... e.g., when timing is involved
... sources are loosely defined; it can be a lot of different
thingns
... hard to check if source is stopped when all track have
ended
jib: we have a hack in firefox where we look at labels
DrAlexG: that won't work for long
dom: we should only test that the
final result is the same
... algorithms are a clear way to define behavior
<dom> applyConstraints ends with a note that says "Any implementation that has the same result as the algorithm above is an allowed implementation"
jib: how are you testing SHOULD-statements
dom: we don't test them
DrAlexG: tricky to test security
permission prompts
... web bluetooth have had the same problem
<dom> "Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent. " https://w3c.github.io/mediacapture-main/getusermedia.html#conformance
dom: issue has been reported to the web driver WG
DrAlexG: (showing slide about
test results from March 2016)
... adapter.js is almost a part of the browser today
dom: we can't give adapter.js to the director :)
hta2: adapter.js hints that the functionality is there but the name is wrong
DrAlexG: summing up test status
dom: are any implementors planning to upstream tests?
DrAlexG: all browsers have their own tests
dom: there have been efforts in other groups to upstream tests
bernard: my opinion is that won't work well for advanced test cases (e.g. with a conferencing server involved)
DrAlexG: there's room for collaboration
hta: the chrome team has been
working hard on importing tests
... and converting tests to w3c platform tests
... I've been thinking about suggesting a fake device for the
web driver spec
DrAlexG: (talks about Apple's approach to give test consent to getUserMedia)
dom: having this is the web driver would be useful
jib: this is different between browsers
dom: it wouldn't have to be with the web driver
DrAlexG: it's up to us or the BT group to make this happen
dom: I can help this activity but not be the driver
hta: basically says: here's how
you tell a media device which device to send audio to
... (showing slide with controversial topics)
<dom> Issue #19 Reserved values for ID don't seem like the right solution
dom: there was an issue in mcap
if we should have a minimum length of ids to avoid
collisions
... that issue was closed pointing to the above issue
fluffy: how do I get the device id for speakers
hta: the speaker device is in the enumerated devices set
fluffy: so I get a label on the speakers after a gum() request?
jib: yes
hta: fingerprinting is the cause to restrict access to labels
dom: there might be future versions of enumerate devices that's disconnected from webrtc
<dom> Issue #173 Consider specifying a minimum length for deviceId
<dom> https://lists.w3.org/Archives/Public/public-media-capture/2015Jun/0015.html
jib: many ways to solve this; we think all of them are ugly
dom: someone from the audio
output spec should get an AP to come up with a solution
... issue 19 is assigned to hta for guido
hta: showing slide about a request to go to CR
PR #784 interToneGap and duration fixes
bernard:PR #784 problem is there is a
default and optional
... remove the default
jib: if it is a method, then the argument is default
<dom> Optional arguments can also have a default value specified. in WebIDL
adambe: you always need a default value unless it is option
burn: if what you want to do is: you want to specify a way to use the last set of values you want to use. such that you want to override it
fluffy: do not like that, it is unintuitive
hta: if you call the
insertDTMF(2, 500) and then call insertDTMF(2), then what is
the expected behaviour?
... in some DTMF engines it clears the tone
decision it is is as is
bernard: the conclusion keep what we have, and is fine from webidl.
dom: It is fine from webidl, but is there an underlying issue we are not addressing
fluffy: can there be more than one DTMF agent
bernard: there is one for each RTP sender
<dom> Conclusion: we need to remove "if insertDTMF was called without specifying the duration. " from the description of the insertMethod operation
<dom> (and likewise for intertonegap)
<dom> Additional conclusion on 782: we don't want to make values sticky
Issue 799 Unclear when a DTMFToneChangeEvent is fired with an empty string
bernard: issue 799
bernard: keep the empty string
when all the tones have finished playback.
... and not at the end of each tone
hta: we accept the proposal
<dom> [conclusion: we accept PR 807]
Issue 800 What happens if removeTrack() is called when DTMF tones are still in the toneBuffer?
bernard: what happens when a
remove track is called when there are tones in the
tonebuffer
... PR #809 is the proposed fix
PR #809 What happens when insertDTMF is called for a stopped sender? (proposed fix)
bernard: there are a few cases i
had in mind
... if the sender is closed, then it should throw invalid state
error.
... if the sender is closing, then abort the process
fluffy: do we send the "tones have been played" event?
hta: no, since tones were not played
fluffy: what if I call
insertDTMF("ABCDEF...Z"), then call insertDTMF(""). Meanwhile,
the DTMF engine had sent A through D. Then the empty string is
executed, which will stop playing the event after the "D" tone
is played.
... so the empty string flushes the previous buffer.
Issue 714 STUN/TURN OAuth token auth parameter passing
bernard: Issue 714, 740
burn: the person who reported the issue turned up at a standards webinar and reported it was not resolved.
<dom> Misi's presentation on OAuth + STUN/TURN
PeterT: is anyone implementing oauth for stun/turn
[no one]
fluffy: ask the TRAM WG to comment on the PR and issue
dom: so part of the question is whether there is any hope of supporting oauth-based auth in 1.0
conclusion: no resolution, action on chair to ask TRAM.
<vivien> https://bugs.chromium.org/p/webrtc/issues/detail?id=4907
<vivien> https://bugzilla.mozilla.org/show_bug.cgi?id=1247616
<vivien> those issues are entitled "Support RFC 7635 (TURN OAuth)"
Issue 305 Describe what happens when media changesPeterT: Issue #305.
fluffy: i thought we decided center and crop
PeterT: what to do about incompatible aspect ratio
jib: we have replace track, this would only happen if there was a violation of what was negotiated
PeterT: the only thing that is negotiated, we do not have a way to set aspect ratio
fluffy: this would only happen if
the media is sent outside the negotiated scope.
... we do not want letterboxing, because it might be a lot of
black... so I prefer center and crop
decision: center, scale, crop, in that order.
<vivien> Meeting adjourned for today
<vivien> see you tomorrow