Hello.
I tried to incorporate Madlld low-level API demonstration code into my MP3 player, but I'm experiencing a weird problem. When data stored by mad_stream_buffer to MAD are going to run out MAD_ERROR_BADHUFFDATA is generated right before MAD_ERROR_BUFLEN. Then when new data are sent to MAD MAD_ERROR_BADCRC and MAD_ERROR_BADDATAPTR occur. Since then no other errors occur until next data are consumed. This produces slight skip in otherwise fluent playback. I checked twice that my code which I'm attaching is equivalent to Madlld's one. Please, if you'll notice a reasong of this behaviour in my code, let me know since I'm little desperate about this.
Thank you.
I'm reposting Miranda's message which was sent as private and I hope that by mistake:
There's an obvious problem in your program, I instruct it in the comments: /* When error occurred while mad_frame_decode, you need do some processing */ if (MAD_RECOVERABLE(this->int_stream.error)) { if (this->int_stream.error != MAD_ERROR_LOSTSYNC || this->int_stream.this_frame != guard_start) { qWarning("Recoverable error during MPEG stream decoding: %x!", this->int_stream.error); } // Decode next frame. continue; } else /* The problem occurres here */ { // Out of MPEG frame data? if (this->int_stream.error == MAD_ERROR_BUFLEN) /* MAD_ERROR_BUFLEN is a kind of recoverable error, i.e, MAD_RECOVERABLE(MAD_ERROR_BUFLEN) == 1, so the condition "if (this->int_stream.error == MAD_ERROR_BUFLEN)" here will never be true, and you do need it to be true when there's no enough data in this->int_stream, so you can read new data into buffer from file. */ { qDebug("need data"); // Read next data from file and try to decode aggain. continue; } else { qWarning("Error decoding MPEG stream: %x!", this->int_stream.error); return -1; } } Hope this will help. Best regards, Miranda
--------------------------------- 雅虎免费邮箱3.5G容量,20M附件!
On Sunday 13 of May 2007 01:53:33 Radek Bartoň wrote:
I'm reposting Miranda's message which was sent as private and I hope that by mistake:
There's an obvious problem in your program, I instruct it in the comments: /* When error occurred while mad_frame_decode, you need do some processing */ if (MAD_RECOVERABLE(this->int_stream.error)) { if (this->int_stream.error != MAD_ERROR_LOSTSYNC || this->int_stream.this_frame != guard_start) { qWarning("Recoverable error during MPEG stream decoding: %x!", this->int_stream.error); } // Decode next frame. continue; } else /* The problem occurres here */ { // Out of MPEG frame data? if (this->int_stream.error == MAD_ERROR_BUFLEN) /* MAD_ERROR_BUFLEN is a kind of recoverable error, i.e, MAD_RECOVERABLE(MAD_ERROR_BUFLEN) == 1, so the condition "if (this->int_stream.error == MAD_ERROR_BUFLEN)" here will never be true, and you do need it to be true when there's no enough data in this->int_stream, so you can read new data into buffer from file. */ { qDebug("need data"); // Read next data from file and try to decode aggain. continue; } else { qWarning("Error decoding MPEG stream: %x!", this->int_stream.error); return -1; } } Hope this will help. Best regards, Miranda
雅虎免费邮箱3.5G容量,20M附件!
I'm sorry, but it didn't. MAD_RECOVERABLE(MAD_ERROR_BUFLEN) is evaluated as false with my MAD 0.15b installation. Anyway, if MAD_RECOVERABLE(MAD_ERROR_BUFLEN) would be true it would work either because with every recoverable error loop is returned to beginning where MAD_ERROR_BUFLEN is tested and new data are passed accordingly.
But thank your for your attention to my problem.
On Apr 29, 2007, at 11:01 AM, Radek Bartoň wrote:
I tried to incorporate Madlld low-level API demonstration code into my MP3 player, but I'm experiencing a weird problem. When data stored by mad_stream_buffer to MAD are going to run out MAD_ERROR_BADHUFFDATA is generated right before MAD_ERROR_BUFLEN. Then when new data are sent to MAD MAD_ERROR_BADCRC and MAD_ERROR_BADDATAPTR occur. Since then no other errors occur until next data are consumed. This produces slight skip in otherwise fluent playback. I checked twice that my code which I'm attaching is equivalent to Madlld's one. Please, if you'll notice a reasong of this behaviour in my code, let me know since I'm little desperate about this.
You should not inspect this->int_stream.error (at line 35) unless mad_decode_frame() returns -1, because this field is not otherwise reset. I suspect you may be loading new data each time through the loop, until another decoding error occurs as a consequence.
On Monday 21 of May 2007 03:04:46 Rob Leslie wrote:
You should not inspect this->int_stream.error (at line 35) unless mad_decode_frame() returns -1, because this field is not otherwise reset. I suspect you may be loading new data each time through the loop, until another decoding error occurs as a consequence.
If I understand your advise correctly, you are saying that I should move code reading new data (lines 35-73) right after MAD_ERROR_BUFLEN detections to line 97? I tried that but result is the same. Moreover reading code is executed first time due fullfilled condition this->int_stream.buffer == NULL and it resets this->int_stream.error to MAD_ERROR_NONE at line 72 each time so next evocation of this code would be due previous MAD_ERROR_BUFLEN and it should be called only once for each MAD_ERROR_BUFLEN error.
The only thing I know about problem is that MAD_ERROR_BADHUFFDATA or any other errors are returned before MAD_ERROR_BUFLEN and this seems like MAD won't recognize that it hasn't complete frame at the end of buffered data, tries to decode it with these errors and then returns MAD_ERROR_BUFLEN. Then after passing new block of data is first frame in buffer of course incomplete too and MAD gets unsynchronized with errors.
The only thing I know about problem is that MAD_ERROR_BADHUFFDATA or any other errors are returned before MAD_ERROR_BUFLEN and this seems like MAD won't recognize that it hasn't complete frame at the end of buffered data, tries to decode it with these errors and then returns MAD_ERROR_BUFLEN. Then after passing new block of data is first frame in buffer of course incomplete too and MAD gets unsynchronized with errors.
I just realized that your mpeg_buffer is on the stack. MAD doesn't copy this buffer; it keeps pointers to it. Unless you're decoding the entire file in one go, this is very likely a source of corruption and consequent decoding errors.
Try moving line 5 outside the function, to file scope.
On Tuesday 22 of May 2007 21:56:58 Rob Leslie wrote:
I just realized that your mpeg_buffer is on the stack. MAD doesn't copy this buffer; it keeps pointers to it. Unless you're decoding the entire file in one go, this is very likely a source of corruption and consequent decoding errors.
Try moving line 5 outside the function, to file scope.
That's it. Thank you very much. I should realize such obvious mistake but sometimes I can't see the forest for trees :-).