Closed
Bug 895730
Opened 12 years ago
Closed 12 years ago
MediaRecorder - Can't get any encoded data from encoder when recording the mediaStream with mute audio
Categories
(Core :: Audio/Video: Recording, defect)
Core
Audio/Video: Recording
Tracking
()
VERIFIED
FIXED
mozilla25
People
(Reporter: rlin, Assigned: shelly)
References
Details
(Whiteboard: [MR1.2])
Attachments
(1 file, 3 obsolete files)
|
5.67 KB,
patch
|
shelly
:
review+
|
Details | Diff | Splinter Review |
STR:
1. use mozGetUserMedia({audio:true, fake = true}) and get mediastream
2. recording this mediastream
NG: mediaRecorder can't get any encoded data from encoder.
The mediaStream already notifyAudioTrackChange to encoder, but I found the encoder isn't output encoded data to recorder. That would affect our automatic test.
| Assignee | ||
Updated•12 years ago
|
Assignee: nobody → slin
| Reporter | ||
Updated•12 years ago
|
Blocks: MediaRecording
| Assignee | ||
Comment 1•12 years ago
|
||
The channels number of a fake audio chunk when using the fake tag in |mozGetUserMedia({audio:true, fake:true})| is zero, this is why the MediaEncoder fails to create an AudioTrackEncoder.
The patch from attachment fixes the problem, but I'm not sure if this is the right fix.
| Assignee | ||
Comment 2•12 years ago
|
||
This fix is base on the assumption where the muted audio is some chunks with valid duration but empty channel data.
Regardless of this bug, it does bring up another issue of the lack of error handling if fail to initialize the audio encoder. Currently, the encoder thread will be blocked by a monitor where it is waiting for a valid encoder.
Attachment #779698 -
Flags: review?(roc)
| Assignee | ||
Updated•12 years ago
|
Whiteboard: [MR1.2]
| Assignee | ||
Comment 3•12 years ago
|
||
Create bug 896980.
Comment on attachment 779698 [details] [diff] [review]
Handle null audio chunk in AudioTrackEncoder
Review of attachment 779698 [details] [diff] [review]:
-----------------------------------------------------------------
::: content/media/encoder/TrackEncoder.cpp
@@ +40,5 @@
> + // A muted audio chunk might have a valid duration but empty channel data,
> + // in this case, we should still initialize the audio track encoder.
> + nsresult rv = Init((chunk.IsNull() && chunk.mDuration > 0) ?
> + DEFAULT_CHANNELS : chunk.mChannelData.Length(),
> + aTrackRate);
We should determine the channel count by searching for the first chunk that is not null.
If all the chunks are null, we should defer the Init call.
However we need to make sure that once we finally see a non-null chunk and call Init, we feed the right amount of null (zero) data into the encoder.
| Assignee | ||
Comment 5•12 years ago
|
||
Hmmm, I got it, thanks Rob :).
Is there a maximum value for the defer? What if we never see a non-null chunk? I can't think of a case like this in real life, but a test case of using fake gUM would hang the encoder and return nothing.
| Assignee | ||
Updated•12 years ago
|
Attachment #779698 -
Flags: review?(roc)
(In reply to Shelly Lin [:shelly] from comment #5)
> Is there a maximum value for the defer? What if we never see a non-null
> chunk? I can't think of a case like this in real life, but a test case of
> using fake gUM would hang the encoder and return nothing.
That means the audio stream is complete silence, so it doesn't matter how many channels you use. I guess when the recording finally ends, then it's OK to default to 1 channel and emit a burst of that much silence. It should compress very well :-).
| Assignee | ||
Comment 7•12 years ago
|
||
This version of fix is closer to our previous discussion.
Attachment #779698 -
Attachment is obsolete: true
Attachment #780816 -
Flags: review?(roc)
| Assignee | ||
Comment 8•12 years ago
|
||
Comment on attachment 780816 [details] [diff] [review]
v2: Handle null audio chunks in AudioTrackEncoder
Review of attachment 780816 [details] [diff] [review]:
-----------------------------------------------------------------
::: content/media/encoder/TrackEncoder.cpp
@@ +79,5 @@
> + if (!mInitialized && mSilentDuration > 0) {
> + Init(DEFAULT_CHANNELS, DEFAULT_SAMPLING_RATE);
> + mRawSegment->AppendNullData(mSilentDuration);
> + mSilentDuration = 0;
> + }
I thought it makes more sense to put the above implementation when receiving a track event of TRACK_EVENT_ENDED (ln:65), but ending the fake gUM doesn't give me a TRACK_EVENT_ENDED event, not sure if this is a bug of fake gUM.
@@ +94,5 @@
>
> + // Drops the aSegment receives from MediaStreamGraph if our queued segment has
> + // overflowed, but not in the case where there is a complete silence before
> + // the audio track encoder has initialized.
> + if (mRawSegment->GetDuration() < MAX_FRAMES_TO_DROP || mSilentDuration > 0) {
This is for preventing the drop of any source segments if we have a very long silence before initializing the audio track encoder.
(In reply to Shelly Lin [:shelly] from comment #8)
> ::: content/media/encoder/TrackEncoder.cpp
> @@ +79,5 @@
> > + if (!mInitialized && mSilentDuration > 0) {
> > + Init(DEFAULT_CHANNELS, DEFAULT_SAMPLING_RATE);
> > + mRawSegment->AppendNullData(mSilentDuration);
> > + mSilentDuration = 0;
> > + }
>
> I thought it makes more sense to put the above implementation when receiving
> a track event of TRACK_EVENT_ENDED (ln:65), but ending the fake gUM doesn't
> give me a TRACK_EVENT_ENDED event, not sure if this is a bug of fake gUM.
I think it is. Can you track it down?
> @@ +94,5 @@
> >
> > + // Drops the aSegment receives from MediaStreamGraph if our queued segment has
> > + // overflowed, but not in the case where there is a complete silence before
> > + // the audio track encoder has initialized.
> > + if (mRawSegment->GetDuration() < MAX_FRAMES_TO_DROP || mSilentDuration > 0) {
>
> This is for preventing the drop of any source segments if we have a very
> long silence before initializing the audio track encoder.
I don't understand why we need to do this. Null AudioChunks don't take up much space. (sequential null chunks should all be combined into a single null chunk automatically.)
| Assignee | ||
Comment 10•12 years ago
|
||
(In reply to Robert O'Callahan (:roc) (Mozilla Corporation) from comment #9)
> (In reply to Shelly Lin [:shelly] from comment #8)
> > ::: content/media/encoder/TrackEncoder.cpp
> > @@ +79,5 @@
> > > + if (!mInitialized && mSilentDuration > 0) {
> > > + Init(DEFAULT_CHANNELS, DEFAULT_SAMPLING_RATE);
> > > + mRawSegment->AppendNullData(mSilentDuration);
> > > + mSilentDuration = 0;
> > > + }
> >
> > I thought it makes more sense to put the above implementation when receiving
> > a track event of TRACK_EVENT_ENDED (ln:65), but ending the fake gUM doesn't
> > give me a TRACK_EVENT_ENDED event, not sure if this is a bug of fake gUM.
>
> I think it is. Can you track it down?
Sure.
>
> > @@ +94,5 @@
> > >
> > > + // Drops the aSegment receives from MediaStreamGraph if our queued segment has
> > > + // overflowed, but not in the case where there is a complete silence before
> > > + // the audio track encoder has initialized.
> > > + if (mRawSegment->GetDuration() < MAX_FRAMES_TO_DROP || mSilentDuration > 0) {
> >
> > This is for preventing the drop of any source segments if we have a very
> > long silence before initializing the audio track encoder.
>
> I don't understand why we need to do this. Null AudioChunks don't take up
> much space. (sequential null chunks should all be combined into a single
> null chunk automatically.)
Say we have received MAX_FRAMES_TO_DROP null chunks and then receive the first non-null chunk with duration N (and this is when the encoder is initialized), the duration of mRawSegment is MAX_FRAMES_TO_DROP because it has already appended this many TrackTicks after the call to Init(), thus the original logic will make it not append this non-null chunk.
An alternative way is to append the null data here, something like:
if (mRawSegment->GetDuration() < MAX_FRAMES_TO_DROP) {
if (mSilentDuration > 0) {
mRawSegment->AppendNullData(mSilentDuration);
mSilentDuration = 0;
}
......
(In reply to Shelly Lin [:shelly] from comment #10)
> if (mRawSegment->GetDuration() < MAX_FRAMES_TO_DROP) {
> if (mSilentDuration > 0) {
> mRawSegment->AppendNullData(mSilentDuration);
> mSilentDuration = 0;
> }
That sounds like it would work.
However, actually I don't understand what MAX_FRAMES_TO_DROP is for. Can you explain it to me?
| Assignee | ||
Comment 12•12 years ago
|
||
(In reply to Robert O'Callahan (:roc) (Mozilla Corporation) from comment #11)
> (In reply to Shelly Lin [:shelly] from comment #10)
> > if (mRawSegment->GetDuration() < MAX_FRAMES_TO_DROP) {
> > if (mSilentDuration > 0) {
> > mRawSegment->AppendNullData(mSilentDuration);
> > mSilentDuration = 0;
> > }
>
> That sounds like it would work.
>
> However, actually I don't understand what MAX_FRAMES_TO_DROP is for. Can you
> explain it to me?
Sure. It was designed for the situation when the pull from recorder is much slower than the receive from MediaStramGraph, we set a limitation from storing raw data to the segment queue in audio track encoder, to avoid buffer overflow or memory burst.
Although I don't think it is necessary since the overhead of audio data is not that big, as oppose to video frames. Me personally would vote for removing this implementation since when it comes to recording video, it'll prefer dropping video frames over dropping audio chunks. How do you think of that?
Yeah, I don't think we should have that. Let's take it out.
We may or may not need it for video. Let's worry about that once we can test for it.
| Assignee | ||
Comment 14•12 years ago
|
||
This patch has removed the implementation of "dropping in-coming frames if the speed of encoding is much slower than receiving in-coming raw data.".
Attachment #780816 -
Attachment is obsolete: true
Attachment #780816 -
Flags: review?(roc)
Attachment #783095 -
Flags: review?(roc)
Comment on attachment 783095 [details] [diff] [review]
v3: Handle null audio chunks in AudioTrackEncoder
Review of attachment 783095 [details] [diff] [review]:
-----------------------------------------------------------------
Great!
::: content/media/encoder/TrackEncoder.cpp
@@ +95,3 @@
> }
> +
> + while(!iter.IsEnded()) {
space before (
Attachment #783095 -
Flags: review?(roc) → review+
| Assignee | ||
Comment 16•12 years ago
|
||
W/ nit fixed and carry r+ from Rob.
Attachment #783095 -
Attachment is obsolete: true
Attachment #783544 -
Flags: review+
| Assignee | ||
Updated•12 years ago
|
Keywords: checkin-needed
| Assignee | ||
Comment 17•12 years ago
|
||
Try server result:
https://tbpl.mozilla.org/?tree=Try&rev=3a54081a6169
Comment 18•12 years ago
|
||
Keywords: checkin-needed
Comment 19•12 years ago
|
||
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla25
Comment 20•12 years ago
|
||
So if I understand this bug correctly - we can't record audio from a fake gUM stream? And this wouldn't work as well if we muted the audio media stream track?
I'll do some exploratory testing around this, but some clarity on the above questions would be helpful.
Comment 21•12 years ago
|
||
Specifically in reference to muting - I'm meaning trying to record a media stream in which the audio media stream track is muted by setting enabled to false.
| Assignee | ||
Comment 22•12 years ago
|
||
My bad, I should have state the change for you :(.
You can, if you record a complete silence, or record with fake gUM, it won't return the blob data periodically during recording. Instead, it'll emit the silent audio data w/ such duration once you stop the recorder.
Flags: needinfo?(slin)
Comment 23•12 years ago
|
||
Verified - confirmed we're getting silence on muted audio recorded.
Status: RESOLVED → VERIFIED
Updated•11 years ago
|
Component: Video/Audio → Video/Audio: Recording
Updated•11 years ago
|
No longer blocks: MediaRecording
You need to log in
before you can comment on or make changes to this bug.
Description
•