Opened 12 years ago

Closed 12 years ago

Last modified 12 years ago

#175 closed defect (fixed)

Bug Report about mp4 module

Reported by: Xietong LU Owned by: somebody
Priority: minor Milestone:
Component: nginx-core Version: 1.3.x
Keywords: Cc:
uname -a:
nginx -V: nginx -V

Description

The ngx_http_mp4_update_stsc_atom function has some bug.

Change History (12)

comment:1 by maxim, 12 years ago

Probably. But could you please provide more information about the bug you discovered?

in reply to:  1 comment:2 by Xietong LU, 12 years ago

Replying to maxim:

Probably. But could you please provide more information about the bug you discovered?

I think there are two bugs and I just found out how to fix one of them.
In line 2491, whenever trak->chunk_samples is true, the variable entries should increase 1.
So entries++; should be added.
I didn't test it yet because I can't compile nginx with my computer.

Last edited 12 years ago by Xietong LU (previous) (diff)

comment:3 by Maxim Dounin, 12 years ago

Could you please instead provide a description of the problem you are seeing, and steps to reproduce it? I think you're right and something like this

--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -2500,6 +2500,8 @@ found:
 
     if (trak->chunk_samples) {
 
+        entries++;
+
         first = &trak->stsc_chunk_entry;
         ngx_mp4_set_32value(first->chunk, 1);
         ngx_mp4_set_32value(first->samples, samples - trak->chunk_samples);

is indeed needed to correctly handle non-keyframe seeks, but it would be good to see the actual problem before trying to fix it.

in reply to:  3 comment:4 by Xietong LU, 12 years ago

Replying to Maxim Dounin:

Could you please instead provide a description of the problem you are seeing, and steps to reproduce it? I think you're right and something like this

--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -2500,6 +2500,8 @@ found:
 
     if (trak->chunk_samples) {
 
+        entries++;
+
         first = &trak->stsc_chunk_entry;
         ngx_mp4_set_32value(first->chunk, 1);
         ngx_mp4_set_32value(first->samples, samples - trak->chunk_samples);

is indeed needed to correctly handle non-keyframe seeks, but it would be good to see the actual problem before trying to fix it.

I use an mp4 file for testing. Inside the sample to chunk box, the original entries are

Entry{firstChunk=1, samplePerChunk=13, sampleDescriptionIndex=1}
Entry{firstChunk=2, samplePerChunk=12, sampleDescriptionIndex=1}
Entry{firstChunk=167, samplePerChunk=9, sampleDescriptionIndex=1}

Then I use wget with different start time to download the regenerated mp4 files. When the start time is 0.1, where the start sample is 2nd one, the new entries are

Entry{firstChunk=1, samplePerChunk=11, sampleDescriptionIndex=1}
Entry{firstChunk=2, samplePerChunk=13, sampleDescriptionIndex=1}
Entry{firstChunk=2, samplePerChunk=12, sampleDescriptionIndex=1}

(I'm using the mp4 parser from the website: http://code.google.com/p/mp4parser/)
Other information is as follow.
type: stsc
size: 64
version: 0
entries: 3

You can find 2 bugs here.

  1. Entry{firstChunk=167, samplePerChunk=9, sampleDescriptionIndex=1} is missing. Actually, this entry is inside the file from the size of this box, but the number of entries is 3. Then the parser didn't show it out.
  2. Entry{firstChunk=2, samplePerChunk=13, sampleDescriptionIndex=1} should be deleted. It happened when the start sample is located in the last chunk specified by an entry. For example, when the start sample are from 1983 - 1993, similar problem will happen again.

My English is poor and I can't express it very clearly.

comment:5 by Xietong LU, 12 years ago

I think the second problem can be solved by this way

+       if (trak->chunk_samples&& (start_sample/samples == next_chunk - chunk)){
+	   ngx_mp4_set_32value(entry->samples, samples - trak->chunk_samples);
+	}
        else if (trak->chunk_samples) {

		entries++; 
		...

comment:6 by Maxim Dounin, 12 years ago

Could you please provide the mp4 file in question for testing?

in reply to:  6 comment:7 by Xietong LU, 12 years ago

Replying to Maxim Dounin:

Could you please provide the mp4 file in question for testing?

The original file.
https://docs.google.com/open?id=0B3Wt0yFGIKL1M21fTDEtM2lUR1k
The output file.
https://docs.google.com/open?id=0B3Wt0yFGIKL1WE16Sm5hb19oX0k

comment:8 by Maxim Dounin, 12 years ago

Ok, thanks. The following patch seems to resolve both issues:

--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -2498,7 +2498,13 @@ found:
 
     ngx_mp4_set_32value(entry->chunk, 1);
 
-    if (trak->chunk_samples) {
+    if (trak->chunk_samples && next_chunk - trak->start_chunk == 2) {
+
+        /* last chunk in the entry */
+
+        ngx_mp4_set_32value(entry->samples, samples - trak->chunk_samples);
+
+    } else if (trak->chunk_samples) {
 
         first = &trak->stsc_chunk_entry;
         ngx_mp4_set_32value(first->chunk, 1);
@@ -2514,6 +2520,7 @@ found:
 
         ngx_mp4_set_32value(entry->chunk, 2);
 
+        entries++;
         atom_size += sizeof(ngx_mp4_stsc_entry_t);
     }
 

Is it looks ok for you?

in reply to:  8 comment:9 by Xietong LU, 12 years ago

Replying to Maxim Dounin:

Ok, thanks. The following patch seems to resolve both issues:

--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -2498,7 +2498,13 @@ found:
 
     ngx_mp4_set_32value(entry->chunk, 1);
 
-    if (trak->chunk_samples) {
+    if (trak->chunk_samples && next_chunk - trak->start_chunk == 2) {
+
+        /* last chunk in the entry */
+
+        ngx_mp4_set_32value(entry->samples, samples - trak->chunk_samples);
+
+    } else if (trak->chunk_samples) {
 
         first = &trak->stsc_chunk_entry;
         ngx_mp4_set_32value(first->chunk, 1);
@@ -2514,6 +2520,7 @@ found:
 
         ngx_mp4_set_32value(entry->chunk, 2);
 
+        entries++;
         atom_size += sizeof(ngx_mp4_stsc_entry_t);
     }
 

Is it looks ok for you?

yes. It looks ok.

comment:10 by Maxim Dounin, 12 years ago

In [4688/nginx]:

Mp4: fixed non-keyframe seeks in some cases (ticket #175).

Number of entries in stsc atom was wrong if we've added an entry to
split a chunk.

Additionally, there is no need to add an entry if we are going to split
last chunk in an entry, it's enough to update the entry we already have.
Previously new entry was added and old one was left as is, resulting in
incorrect entry with zero chunks which might confuse some software.

comment:11 by Maxim Dounin, 12 years ago

Resolution: fixed
Status: newclosed

Fix committed, thanks.

comment:12 by Maxim Dounin, 12 years ago

In [4728/nginx]:

Merge of r4688, r4689, r4706:

*) Mp4: fixed non-keyframe seeks in some cases (ticket #175).

Number of entries in stsc atom was wrong if we've added an entry to
split a chunk.

Additionally, there is no need to add an entry if we are going to split
last chunk in an entry, it's enough to update the entry we already have.
Previously new entry was added and old one was left as is, resulting in
incorrect entry with zero chunks which might confuse some software.

*) Mp4: fixed streaming if moov atom is at buffer edge.

Note: See TracTickets for help on using tickets.