|
|
Created:
7 years, 6 months ago by jrummell Modified:
7 years, 6 months ago CC:
chromium-reviews, feature-media-reviews_chromium.org Base URL:
https://chromium.googlesource.com/chromium/src.git@master Visibility:
Public. |
DescriptionAdd new class AudioBufferQueue.
As part of the work to simplify the handling of audio data, adding this
class to create a queue of audio data. Using this class will come in a
subsequent CL.
BUG=248989
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=207761
Patch Set 1 #
Total comments: 32
Patch Set 2 : #
Total comments: 22
Patch Set 3 : #
Total comments: 10
Patch Set 4 : #
Messages
Total messages: 14 (0 generated)
Next step in the audio data improvements. PTAL.
https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... File media/base/seekable_audio_buffer.cc (right): https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:25: void SeekableAudioBuffer::Clear() { do we ever call this method in production? can we get away with re-allocating the object, or is that crazy talk? if we decide with keeping it, one tiny improvement we can do in this file is to have the ctor call Clear() instead of duplicating initialization code https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:57: DCHECK(dest); don't need to DCHECK pointers we immediately dereference here + rest of file https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:72: if (frames > forward_frames_) think this can be a CHECK()? I like APIs that fail horribly if you do something stupid. It's too easy to not check the return value of a function returning a bool :) https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... File media/base/seekable_audio_buffer.h (right): https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:5: // SeekableAudioBuffer to support forward seeking in a buffer for reading a this should go by the class as opposed to top of file yes, chrome as a whole in inconsistent but in media/ we try to be consistent :) https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:31: #include "media/base/audio_buffer.h" can we fwd decl AudioBuffer? https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:38: class MEDIA_EXPORT SeekableAudioBuffer { I've never particularly liked the "seekable" name, and with this AudioBuffer-specific version it's even less seekable since we can only ever move forward! WDYT about AudioBufferQueue? https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:41: SeekableAudioBuffer(int forward_capacity); one thing I've always wanted to consider is whether we could remove the capacity logic from this class and have the owner (e.g., AudioRendererImpl) manage its own capacity logic, since its the one that ultimately cares and manages capacity then this class is simply a queue of buffers to facilitate reading across many AudioBuffers https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:74: int forward_capacity() const { return forward_capacity_; } should we drop the forward prefix considering there's only one direction? https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:93: typedef std::list<scoped_refptr<AudioBuffer> > BufferQueue; this (and the regular SeekableBuffer!) should be a deque given the typical usage of this class (pops off the front + pushes on the back, no random insertion/deletion in middle, tiny element size) https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:121: DISALLOW_COPY_AND_ASSIGN(SeekableAudioBuffer); IMPLICIT as we don't define the default ctor https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... File media/base/seekable_audio_buffer_unittest.cc (right): https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer_unittest.cc:19: static scoped_refptr<AudioBuffer> MakeInterleavedBuffer( are these duplicated from audio_buffer_unittest.cc? IWBN to stick them into some common code somewhere ... let's go with media/base/test_helpers.h
Nice work! https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... File media/base/seekable_audio_buffer.cc (right): https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:36: buffers_.push_back(buffer_in); Does this not invalidate the current_buffer_ iterator? http://stackoverflow.com/questions/6438086/iterator-invalidation-rules/644282... https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:41: DCHECK_EQ(0, forward_frames_); no yoda conditions. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:160: while (true) { buffers_.erase(buffers_.begin(), current_buffer_)? Not sure if that will result in current_buffer_ being invalidated. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:174: int64 time_offset = ((*buffer)->duration().InMicroseconds() * offset) / Use InMicrosecondsF() and round up by adding 0.5? https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... File media/base/seekable_audio_buffer.h (right): https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:41: SeekableAudioBuffer(int forward_capacity); On 2013/06/19 23:38:06, scherkus wrote: > one thing I've always wanted to consider is whether we could remove the capacity > logic from this class and have the owner (e.g., AudioRendererImpl) manage its > own capacity logic, since its the one that ultimately cares and manages capacity > > then this class is simply a queue of buffers to facilitate reading across many > AudioBuffers +1 if we can. AudioRendererAlgorithm, AudioRendererImpl, and SeekableBuffer all have a sad coupling around capacity. Ideally exposing a frames() variable should be enough for SeekableAudioBuffer, AudioRendererAlgorithm or AudioRendererImpl can then maintain the proper watermarks.
https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... File media/base/seekable_audio_buffer.cc (right): https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:41: DCHECK_EQ(0, forward_frames_); On 2013/06/20 00:49:49, DaleCurtis wrote: > no yoda conditions. I feel I should elaborate on this. The gtest EXPECT_EQ() macro __is the only ones__ where we do yoda comparisons since its API actually wants the expected value first so that it can print out very pretty and well-formatted text. All other macros ([D]CHECK_XX(), EXPECT_LT, EXPECT_NE) don't discriminate, so we like to have them not be all yoda-y. For reference, here's the most recent discussion we had on the topic: http://goto.google.com/videostack-yoda
I should also clarify that my iterator comments are if you switch to deque as scherkus suggested, list is safe.
Changes as requested. I also renamed the class to AudioBufferQueue. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... File media/base/seekable_audio_buffer.cc (right): https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:25: void SeekableAudioBuffer::Clear() { On 2013/06/19 23:38:06, scherkus wrote: > do we ever call this method in production? > > can we get away with re-allocating the object, or is that crazy talk? > > if we decide with keeping it, one tiny improvement we can do in this file is to > have the ctor call Clear() instead of duplicating initialization code Clear() is called by alsa_output.cc, pulse_input.cc, pulse_unified.cc, and audio_renderer_algorithm.cc. ctor now calls Clear(). https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:36: buffers_.push_back(buffer_in); On 2013/06/20 00:49:49, DaleCurtis wrote: > Does this not invalidate the current_buffer_ iterator? > > http://stackoverflow.com/questions/6438086/iterator-invalidation-rules/644282... For list, no. But for deque it does, so fixed. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:41: DCHECK_EQ(0, forward_frames_); On 2013/06/20 00:49:49, DaleCurtis wrote: > no yoda conditions. Done. However, test code updated to have lots of yoda conditions :) https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:57: DCHECK(dest); On 2013/06/19 23:38:06, scherkus wrote: > don't need to DCHECK pointers we immediately dereference > > here + rest of file Done. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:72: if (frames > forward_frames_) On 2013/06/19 23:38:06, scherkus wrote: > think this can be a CHECK()? > > I like APIs that fail horribly if you do something stupid. It's too easy to not > check the return value of a function returning a bool :) > Done. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:160: while (true) { On 2013/06/20 00:49:49, DaleCurtis wrote: > buffers_.erase(buffers_.begin(), current_buffer_)? > > Not sure if that will result in current_buffer_ being invalidated. Done. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.cc:174: int64 time_offset = ((*buffer)->duration().InMicroseconds() * offset) / On 2013/06/20 00:49:49, DaleCurtis wrote: > Use InMicrosecondsF() and round up by adding 0.5? There is no InMicrosecondsF(), since TimeDelta is stored as a microseconds int64. Converted to a float operation to get the rounding. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... File media/base/seekable_audio_buffer.h (right): https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:5: // SeekableAudioBuffer to support forward seeking in a buffer for reading a On 2013/06/19 23:38:06, scherkus wrote: > this should go by the class as opposed to top of file > > yes, chrome as a whole in inconsistent but in media/ we try to be consistent :) Done. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:31: #include "media/base/audio_buffer.h" On 2013/06/19 23:38:06, scherkus wrote: > can we fwd decl AudioBuffer? scoped_ptr (for list/deque) needs the class defined. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:38: class MEDIA_EXPORT SeekableAudioBuffer { On 2013/06/19 23:38:06, scherkus wrote: > I've never particularly liked the "seekable" name, and with this > AudioBuffer-specific version it's even less seekable since we can only ever move > forward! > > WDYT about AudioBufferQueue? Done. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:41: SeekableAudioBuffer(int forward_capacity); On 2013/06/20 00:49:49, DaleCurtis wrote: > On 2013/06/19 23:38:06, scherkus wrote: > > one thing I've always wanted to consider is whether we could remove the > capacity > > logic from this class and have the owner (e.g., AudioRendererImpl) manage its > > own capacity logic, since its the one that ultimately cares and manages > capacity > > > > then this class is simply a queue of buffers to facilitate reading across many > > AudioBuffers > > +1 if we can. AudioRendererAlgorithm, AudioRendererImpl, and SeekableBuffer all > have a sad coupling around capacity. Ideally exposing a frames() variable should > be enough for SeekableAudioBuffer, AudioRendererAlgorithm or AudioRendererImpl > can then maintain the proper watermarks. Done. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:74: int forward_capacity() const { return forward_capacity_; } On 2013/06/19 23:38:06, scherkus wrote: > should we drop the forward prefix considering there's only one direction? Removed completely. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:93: typedef std::list<scoped_refptr<AudioBuffer> > BufferQueue; On 2013/06/19 23:38:06, scherkus wrote: > this (and the regular SeekableBuffer!) should be a deque given the typical usage > of this class (pops off the front + pushes on the back, no random > insertion/deletion in middle, tiny element size) Done. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer.h:121: DISALLOW_COPY_AND_ASSIGN(SeekableAudioBuffer); On 2013/06/19 23:38:06, scherkus wrote: > IMPLICIT as we don't define the default ctor There is now a default ctor. https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... File media/base/seekable_audio_buffer_unittest.cc (right): https://codereview.chromium.org/17112016/diff/1/media/base/seekable_audio_buf... media/base/seekable_audio_buffer_unittest.cc:19: static scoped_refptr<AudioBuffer> MakeInterleavedBuffer( On 2013/06/19 23:38:06, scherkus wrote: > are these duplicated from audio_buffer_unittest.cc? > > IWBN to stick them into some common code somewhere ... let's go with > media/base/test_helpers.h Done.
https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... File media/base/audio_buffer_queue.cc (right): https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:52: int forward_offset, fix indent https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:66: bool advance_position, fix indent https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:151: int offset) { fix indent https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... File media/base/audio_buffer_queue.h (right): https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.h:44: int PeekFrames(int frames, AudioBus* dest) { how many calls to do we have for each version of PeekFrames()? is it enough to warrant having both versions? in general we try to avoid overloading methods https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... File media/base/audio_buffer_queue_unittest.cc (right): https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue_unittest.cc:19: void VerifyResult(float* channel_data, static to avoid possible collisions https://codereview.chromium.org/17112016/diff/10001/media/base/test_helpers.h File media/base/test_helpers.h (right): https://codereview.chromium.org/17112016/diff/10001/media/base/test_helpers.h... media/base/test_helpers.h:94: DCHECK(format == kSampleFormatU8 || format == kSampleFormatS16 || can you move the impl into the .cc and instantiate the templates for the types we need? (float, uint8, int16, int32)
https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... File media/base/audio_buffer_queue.cc (right): https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:36: if (first_buffer_) { Is it enough to just check if current_time_ is kNoTimestamp() ? https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:43: frames_ += buffer_in->frame_count(); It's possible this could overflow, maybe CHECK_GT(frames, 0) ? https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:52: int forward_offset, Fix indent. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:66: bool advance_position, Fix indent. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:119: BufferQueue::iterator next = current_buffer; Does current_buffer + 1 work? https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:144: buffers_.erase(buffers_.begin(), current_buffer_); Did you figure out if this invalidates current_buffer_ ? Seems like it shouldn't, but worth checking :)
Changes as suggested. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... File media/base/audio_buffer_queue.cc (right): https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:36: if (first_buffer_) { On 2013/06/20 22:08:59, DaleCurtis wrote: > Is it enough to just check if current_time_ is kNoTimestamp() ? I don't know if there are cases where you can push a bunch of buffers with kNoTimeStamp(), and then start using timestamps later. However, I think the buffers_.empty() might be a better test, as long as the insert is done after the test. Changed. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:43: frames_ += buffer_in->frame_count(); On 2013/06/20 22:08:59, DaleCurtis wrote: > It's possible this could overflow, maybe CHECK_GT(frames, 0) ? Done. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:52: int forward_offset, On 2013/06/20 22:08:59, DaleCurtis wrote: > Fix indent. Done. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:66: bool advance_position, On 2013/06/20 22:08:59, DaleCurtis wrote: > Fix indent. Done. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:119: BufferQueue::iterator next = current_buffer; On 2013/06/20 22:08:59, DaleCurtis wrote: > Does current_buffer + 1 work? Done. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:144: buffers_.erase(buffers_.begin(), current_buffer_); On 2013/06/20 22:08:59, DaleCurtis wrote: > Did you figure out if this invalidates current_buffer_ ? Seems like it > shouldn't, but worth checking :) According to the stackoverflow page referenced in previous comments, "erasing the first element invalidates only iterators and references to the erased elements;", so it shouldn't affect current_buffer_. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:151: int offset) { On 2013/06/20 22:05:15, scherkus wrote: > fix indent Done. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... File media/base/audio_buffer_queue.h (right): https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue.h:44: int PeekFrames(int frames, AudioBus* dest) { On 2013/06/20 22:05:15, scherkus wrote: > how many calls to do we have for each version of PeekFrames()? > > is it enough to warrant having both versions? in general we try to avoid > overloading methods Peek (w/offset) called from audio_renderer_algorithm.cc (to support slower playback). Peek (w/o offset) only called from test code, so I have removed it. https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... File media/base/audio_buffer_queue_unittest.cc (right): https://codereview.chromium.org/17112016/diff/10001/media/base/audio_buffer_q... media/base/audio_buffer_queue_unittest.cc:19: void VerifyResult(float* channel_data, On 2013/06/20 22:05:15, scherkus wrote: > static to avoid possible collisions Done. https://codereview.chromium.org/17112016/diff/10001/media/base/test_helpers.h File media/base/test_helpers.h (right): https://codereview.chromium.org/17112016/diff/10001/media/base/test_helpers.h... media/base/test_helpers.h:94: DCHECK(format == kSampleFormatU8 || format == kSampleFormatS16 || On 2013/06/20 22:05:15, scherkus wrote: > can you move the impl into the .cc and instantiate the templates for the types > we need? (float, uint8, int16, int32) Done.
lgtm w/ nits nice!! https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.cc File media/base/test_helpers.cc (right): https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.c... media/base/test_helpers.cc:220: template scoped_refptr<AudioBuffer> MakeInterleavedAudioBuffer<uint8>( if you want you can create a macro to cut down on the repeated text https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.h File media/base/test_helpers.h (right): https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.h... media/base/test_helpers.h:87: scoped_refptr<AudioBuffer> MakeInterleavedAudioBuffer( given these are public methods let's get some docs here + below https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.h... media/base/test_helpers.h:93: const base::TimeDelta start_time); is this supposed to be const-ref? otherwise you could drop the const https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.h... media/base/test_helpers.h:102: const base::TimeDelta start_time); ditto
lgtm % scherkus' comments. https://codereview.chromium.org/17112016/diff/17001/media/base/audio_buffer_q... File media/base/audio_buffer_queue.cc (right): https://codereview.chromium.org/17112016/diff/17001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:152: current_time_ = Formatting looks really odd, but clang-format seems to approve.
Thanks for the reviews. https://codereview.chromium.org/17112016/diff/17001/media/base/audio_buffer_q... File media/base/audio_buffer_queue.cc (right): https://codereview.chromium.org/17112016/diff/17001/media/base/audio_buffer_q... media/base/audio_buffer_queue.cc:152: current_time_ = On 2013/06/21 00:44:22, DaleCurtis wrote: > Formatting looks really odd, but clang-format seems to approve. I generally let clang-format do it's thing, so this is how it formatted it. https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.cc File media/base/test_helpers.cc (right): https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.c... media/base/test_helpers.cc:220: template scoped_refptr<AudioBuffer> MakeInterleavedAudioBuffer<uint8>( On 2013/06/20 23:36:24, scherkus wrote: > if you want you can create a macro to cut down on the repeated text Done. https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.h File media/base/test_helpers.h (right): https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.h... media/base/test_helpers.h:87: scoped_refptr<AudioBuffer> MakeInterleavedAudioBuffer( On 2013/06/20 23:36:24, scherkus wrote: > given these are public methods let's get some docs here + below Done. https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.h... media/base/test_helpers.h:93: const base::TimeDelta start_time); On 2013/06/20 23:36:24, scherkus wrote: > is this supposed to be const-ref? > > otherwise you could drop the const Done. https://codereview.chromium.org/17112016/diff/17001/media/base/test_helpers.h... media/base/test_helpers.h:102: const base::TimeDelta start_time); On 2013/06/20 23:36:24, scherkus wrote: > ditto Done.
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/jrummell@chromium.org/17112016/17004
Message was sent while issue was closed.
Change committed as 207761 |