Changeset 5620:0a567878254b in nginx


Ignore:
Timestamp:
03/20/14 12:05:19 (4 years ago)
Author:
Roman Arutyunyan <arut@…>
Branch:
default
Message:

Mp4: added "end" argument support.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/http/modules/ngx_http_mp4_module.c

    r5619 r5620  
    2828#define NGX_HTTP_MP4_CTTS_DATA    16
    2929#define NGX_HTTP_MP4_STSC_ATOM    17
    30 #define NGX_HTTP_MP4_STSC_CHUNK   18
     30#define NGX_HTTP_MP4_STSC_START   18
    3131#define NGX_HTTP_MP4_STSC_DATA    19
    32 #define NGX_HTTP_MP4_STSZ_ATOM    20
    33 #define NGX_HTTP_MP4_STSZ_DATA    21
    34 #define NGX_HTTP_MP4_STCO_ATOM    22
    35 #define NGX_HTTP_MP4_STCO_DATA    23
    36 #define NGX_HTTP_MP4_CO64_ATOM    24
    37 #define NGX_HTTP_MP4_CO64_DATA    25
     32#define NGX_HTTP_MP4_STSC_END     20
     33#define NGX_HTTP_MP4_STSZ_ATOM    21
     34#define NGX_HTTP_MP4_STSZ_DATA    22
     35#define NGX_HTTP_MP4_STCO_ATOM    23
     36#define NGX_HTTP_MP4_STCO_DATA    24
     37#define NGX_HTTP_MP4_CO64_ATOM    25
     38#define NGX_HTTP_MP4_CO64_DATA    26
    3839
    3940#define NGX_HTTP_MP4_LAST_ATOM    NGX_HTTP_MP4_CO64_DATA
     
    6364
    6465    ngx_uint_t            start_sample;
     66    ngx_uint_t            end_sample;
    6567    ngx_uint_t            start_chunk;
    66     ngx_uint_t            chunk_samples;
    67     uint64_t              chunk_samples_size;
     68    ngx_uint_t            end_chunk;
     69    ngx_uint_t            start_chunk_samples;
     70    ngx_uint_t            end_chunk_samples;
     71    uint64_t              start_chunk_samples_size;
     72    uint64_t              end_chunk_samples_size;
    6873    off_t                 start_offset;
     74    off_t                 end_offset;
    6975
    7076    size_t                tkhd_size;
     
    96102    ngx_buf_t             ctts_data_buf;
    97103    ngx_buf_t             stsc_atom_buf;
    98     ngx_buf_t             stsc_chunk_buf;
     104    ngx_buf_t             stsc_start_chunk_buf;
     105    ngx_buf_t             stsc_end_chunk_buf;
    99106    ngx_buf_t             stsc_data_buf;
    100107    ngx_buf_t             stsz_atom_buf;
     
    105112    ngx_buf_t             co64_data_buf;
    106113
    107     ngx_mp4_stsc_entry_t  stsc_chunk_entry;
     114    ngx_mp4_stsc_entry_t  stsc_start_chunk_entry;
     115    ngx_mp4_stsc_entry_t  stsc_end_chunk_entry;
    108116} ngx_http_mp4_trak_t;
    109117
     
    122130    off_t                 content_length;
    123131    ngx_uint_t            start;
     132    ngx_uint_t            length;
    124133    uint32_t              timescale;
    125134    ngx_http_request_t   *request;
     
    220229    uint64_t atom_data_size);
    221230static size_t ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4,
    222     off_t start_offset);
     231    off_t start_offset, off_t end_offset);
    223232static ngx_int_t ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4,
    224233    uint64_t atom_data_size);
     
    260269    ngx_http_mp4_trak_t *trak);
    261270static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
    262     ngx_http_mp4_trak_t *trak);
     271    ngx_http_mp4_trak_t *trak, ngx_uint_t start);
    263272static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4,
    264273    uint64_t atom_data_size);
     
    266275    ngx_http_mp4_trak_t *trak);
    267276static void ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
    268     ngx_http_mp4_trak_t *trak);
     277    ngx_http_mp4_trak_t *trak, ngx_uint_t start);
    269278static ngx_int_t ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4,
    270279    uint64_t atom_data_size);
     
    272281    ngx_http_mp4_trak_t *trak);
    273282static void ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
    274     ngx_http_mp4_trak_t *trak);
     283    ngx_http_mp4_trak_t *trak, ngx_uint_t start);
    275284static ngx_int_t ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4,
    276285    uint64_t atom_data_size);
     
    278287    ngx_http_mp4_trak_t *trak);
    279288static ngx_int_t ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
    280     ngx_http_mp4_trak_t *trak);
     289    ngx_http_mp4_trak_t *trak, ngx_uint_t start);
    281290static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4,
    282291    uint64_t atom_data_size);
     
    412421    u_char                    *last;
    413422    size_t                     root;
    414     ngx_int_t                  rc, start;
    415     ngx_uint_t                 level;
     423    ngx_int_t                  rc, start, end;
     424    ngx_uint_t                 level, length;
    416425    ngx_str_t                  path, value;
    417426    ngx_log_t                 *log;
     
    518527
    519528    start = -1;
     529    length = 0;
    520530    r->headers_out.content_length_n = of.size;
    521531    mp4 = NULL;
     
    539549            }
    540550        }
     551
     552        if (ngx_http_arg(r, (u_char *) "end", 3, &value) == NGX_OK) {
     553
     554            ngx_set_errno(0);
     555            end = (int) (strtod((char *) value.data, NULL) * 1000);
     556
     557            if (ngx_errno != 0) {
     558                end = -1;
     559            }
     560
     561            if (end > 0) {
     562                if (start < 0) {
     563                    start = 0;
     564                }
     565
     566                if (end > start) {
     567                    length = end - start;
     568                }
     569            }
     570        }
    541571    }
    542572
     
    554584        mp4->end = of.size;
    555585        mp4->start = (ngx_uint_t) start;
     586        mp4->length = length;
    556587        mp4->request = r;
    557588
     
    659690ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
    660691{
    661     off_t                  start_offset, adjustment;
     692    off_t                  start_offset, end_offset, adjustment;
    662693    ngx_int_t              rc;
    663694    ngx_uint_t             i, j;
     
    666697    ngx_http_mp4_conf_t   *conf;
    667698
    668     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
    669                    "mp4 start:%ui", mp4->start);
     699    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     700                   "mp4 start:%ui, length:%ui", mp4->start, mp4->length);
    670701
    671702    conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
     
    709740
    710741    start_offset = mp4->end;
     742    end_offset = 0;
    711743    trak = mp4->trak.elts;
    712744
     
    756788        }
    757789
     790        if (end_offset < trak[i].end_offset) {
     791            end_offset = trak[i].end_offset;
     792        }
     793
    758794        *prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM];
    759795        prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM].next;
     
    767803    }
    768804
     805    if (end_offset < start_offset) {
     806        end_offset = start_offset;
     807    }
     808
    769809    mp4->moov_size += 8;
    770810
     
    783823
    784824    adjustment = mp4->ftyp_size + mp4->moov_size
    785                  + ngx_http_mp4_update_mdat_atom(mp4, start_offset)
     825                 + ngx_http_mp4_update_mdat_atom(mp4, start_offset, end_offset)
    786826                 - start_offset;
    787827
     
    10271067    no_mdat = (mp4->mdat_atom.buf == NULL);
    10281068
    1029     if (no_mdat && mp4->start == 0) {
     1069    if (no_mdat && mp4->start == 0 && mp4->length == 0) {
    10301070        /*
    10311071         * send original file if moov atom resides before
     
    11261166
    11271167static size_t
    1128 ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset)
     1168ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset,
     1169    off_t end_offset)
    11291170{
    11301171    off_t       atom_data_size;
     
    11341175    ngx_buf_t  *atom;
    11351176
    1136     atom_data_size = mp4->mdat_data.buf->file_last - start_offset;
     1177    atom_data_size = end_offset - start_offset;
    11371178    mp4->mdat_data.buf->file_pos = start_offset;
     1179    mp4->mdat_data.buf->file_last = end_offset;
    11381180
    11391181    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     
    12171259    size_t                  atom_size;
    12181260    uint32_t                timescale;
    1219     uint64_t                duration, start_time;
     1261    uint64_t                duration, start_time, length_time;
    12201262    ngx_buf_t              *atom;
    12211263    ngx_mp4_mvhd_atom_t    *mvhd_atom;
     
    12701312
    12711313    duration -= start_time;
     1314
     1315    if (mp4->length) {
     1316        length_time = (uint64_t) mp4->length * timescale / 1000;
     1317
     1318        if (duration > length_time) {
     1319            duration = length_time;
     1320        }
     1321    }
    12721322
    12731323    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     
    14161466    u_char                 *atom_header;
    14171467    size_t                  atom_size;
    1418     uint64_t                duration, start_time;
     1468    uint64_t                duration, start_time, length_time;
    14191469    ngx_buf_t              *atom;
    14201470    ngx_http_mp4_trak_t    *trak;
     
    14651515
    14661516    duration -= start_time;
     1517
     1518    if (mp4->length) {
     1519        length_time = (uint64_t) mp4->length * mp4->timescale / 1000;
     1520
     1521        if (duration > length_time) {
     1522            duration = length_time;
     1523        }
     1524    }
    14671525
    14681526    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     
    15671625    size_t                  atom_size;
    15681626    uint32_t                timescale;
    1569     uint64_t                duration, start_time;
     1627    uint64_t                duration, start_time, length_time;
    15701628    ngx_buf_t              *atom;
    15711629    ngx_http_mp4_trak_t    *trak;
     
    16181676
    16191677    duration -= start_time;
     1678
     1679    if (mp4->length) {
     1680        length_time = (uint64_t) mp4->length * timescale / 1000;
     1681
     1682        if (duration > length_time) {
     1683            duration = length_time;
     1684        }
     1685    }
    16201686
    16211687    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     
    20112077    }
    20122078
    2013     if (ngx_http_mp4_crop_stts_data(mp4, trak) != NGX_OK) {
     2079    if (ngx_http_mp4_crop_stts_data(mp4, trak, 1) != NGX_OK) {
     2080        return NGX_ERROR;
     2081    }
     2082
     2083    if (ngx_http_mp4_crop_stts_data(mp4, trak, 0) != NGX_OK) {
    20142084        return NGX_ERROR;
    20152085    }
     
    20292099static ngx_int_t
    20302100ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
    2031     ngx_http_mp4_trak_t *trak)
    2032 {
    2033     uint32_t               count, duration;
     2101    ngx_http_mp4_trak_t *trak, ngx_uint_t start)
     2102{
     2103    uint32_t               count, duration, rest;
    20342104    uint64_t               start_time;
    20352105    ngx_buf_t             *data;
    2036     ngx_uint_t             start_sample, entries;
     2106    ngx_uint_t             start_sample, entries, start_sec;
    20372107    ngx_mp4_stts_entry_t  *entry, *end;
    20382108
     2109    if (start) {
     2110        start_sec = mp4->start;
     2111
     2112    } else if (mp4->length) {
     2113        start_sec = mp4->length;
     2114
     2115    } else {
     2116        return NGX_OK;
     2117    }
     2118
    20392119    data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
    20402120
    2041     start_time = (uint64_t) mp4->start * trak->timescale / 1000;
     2121    start_time = (uint64_t) start_sec * trak->timescale / 1000;
    20422122
    20432123    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     
    20582138        if (start_time < (uint64_t) count * duration) {
    20592139            start_sample += (ngx_uint_t) (start_time / duration);
    2060             count -= (uint32_t) (start_time / duration);
    2061             ngx_mp4_set_32value(entry->count, count);
     2140            rest = (uint32_t) (start_time / duration);
    20622141            goto found;
    20632142        }
     
    20802159                   "start_sample:%ui, new count:%uD", start_sample, count);
    20812160
    2082     trak->time_to_sample_entries = entries;
    2083     trak->start_sample = start_sample;
    2084     data->pos = (u_char *) entry;
     2161    if (start) {
     2162        ngx_mp4_set_32value(entry->count, count - rest);
     2163        data->pos = (u_char *) entry;
     2164        trak->time_to_sample_entries = entries;
     2165        trak->start_sample = start_sample;
     2166
     2167    } else {
     2168        ngx_mp4_set_32value(entry->count, rest);
     2169        data->last = (u_char *) (entry + 1);
     2170        trak->time_to_sample_entries -= entries - 1;
     2171        trak->end_sample = trak->start_sample + start_sample;
     2172    }
    20852173
    20862174    return NGX_OK;
     
    21832271    }
    21842272
    2185     ngx_http_mp4_crop_stss_data(mp4, trak);
     2273    ngx_http_mp4_crop_stss_data(mp4, trak, 1);
     2274    ngx_http_mp4_crop_stss_data(mp4, trak, 0);
    21862275
    21872276    entry = (uint32_t *) data->pos;
     
    22122301static void
    22132302ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
    2214     ngx_http_mp4_trak_t *trak)
     2303    ngx_http_mp4_trak_t *trak, ngx_uint_t start)
    22152304{
    22162305    uint32_t     sample, start_sample, *entry, *end;
     
    22182307    ngx_uint_t   entries;
    22192308
     2309    /* sync samples starts from 1 */
     2310
     2311    if (start) {
     2312        start_sample = trak->start_sample + 1;
     2313
     2314    } else if (mp4->length) {
     2315        start_sample = trak->end_sample + 1;
     2316
     2317    } else {
     2318        return;
     2319    }
     2320
    22202321    data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf;
    22212322
    2222     /* sync samples starts from 1 */
    2223     start_sample = trak->start_sample + 1;
    22242323    entries = trak->sync_samples_entries;
    2225 
    22262324    entry = (uint32_t *) data->pos;
    22272325    end = (uint32_t *) data->last;
     
    22462344found:
    22472345
    2248     data->pos = (u_char *) entry;
    2249     trak->sync_samples_entries = entries;
     2346    if (start) {
     2347        data->pos = (u_char *) entry;
     2348        trak->sync_samples_entries = entries;
     2349
     2350    } else {
     2351        data->last = (u_char *) entry;
     2352        trak->sync_samples_entries -= entries;
     2353    }
    22502354}
    22512355
     
    23502454    }
    23512455
    2352     ngx_http_mp4_crop_ctts_data(mp4, trak);
     2456    ngx_http_mp4_crop_ctts_data(mp4, trak, 1);
     2457    ngx_http_mp4_crop_ctts_data(mp4, trak, 0);
    23532458
    23542459    if (trak->composition_offset_entries == 0) {
     
    23732478static void
    23742479ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
    2375     ngx_http_mp4_trak_t *trak)
    2376 {
    2377     uint32_t               count, start_sample;
     2480    ngx_http_mp4_trak_t *trak, ngx_uint_t start)
     2481{
     2482    uint32_t               count, start_sample, rest;
    23782483    ngx_buf_t             *data;
    23792484    ngx_uint_t             entries;
    23802485    ngx_mp4_ctts_entry_t  *entry, *end;
    23812486
     2487    /* sync samples starts from 1 */
     2488
     2489    if (start) {
     2490        start_sample = trak->start_sample + 1;
     2491
     2492    } else if (mp4->length) {
     2493        start_sample = trak->end_sample - trak->start_sample + 1;
     2494
     2495    } else {
     2496        return;
     2497    }
     2498
    23822499    data = trak->out[NGX_HTTP_MP4_CTTS_DATA].buf;
    23832500
    2384     /* sync samples starts from 1 */
    2385     start_sample = trak->start_sample + 1;
    23862501    entries = trak->composition_offset_entries;
    23872502    entry = (ngx_mp4_ctts_entry_t *) data->pos;
     
    23962511
    23972512         if (start_sample <= count) {
    2398              count -= (start_sample - 1);
    2399              ngx_mp4_set_32value(entry->count, count);
     2513             rest = start_sample - 1;
    24002514             goto found;
    24012515         }
     
    24062520    }
    24072521
    2408     data->pos = (u_char *) end;
    2409     trak->composition_offset_entries = 0;
     2522    if (start) {
     2523        data->pos = (u_char *) end;
     2524        trak->composition_offset_entries = 0;
     2525    }
    24102526
    24112527    return;
     
    24132529found:
    24142530
    2415     data->pos = (u_char *) entry;
    2416     trak->composition_offset_entries = entries;
     2531    if (start) {
     2532        ngx_mp4_set_32value(entry->count, count - rest);
     2533        data->pos = (u_char *) entry;
     2534        trak->composition_offset_entries = entries;
     2535
     2536    } else {
     2537        ngx_mp4_set_32value(entry->count, rest);
     2538        data->last = (u_char *) (entry + 1);
     2539        trak->composition_offset_entries -= entries - 1;
     2540    }
    24172541}
    24182542
     
    25232647    }
    25242648
    2525     if (ngx_http_mp4_crop_stsc_data(mp4, trak) != NGX_OK) {
     2649    if (ngx_http_mp4_crop_stsc_data(mp4, trak, 1) != NGX_OK) {
     2650        return NGX_ERROR;
     2651    }
     2652
     2653    if (ngx_http_mp4_crop_stsc_data(mp4, trak, 0) != NGX_OK) {
    25262654        return NGX_ERROR;
    25272655    }
     
    25542682static ngx_int_t
    25552683ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
    2556     ngx_http_mp4_trak_t *trak)
    2557 {
    2558     uint32_t               start_sample, chunk, samples, id, next_chunk, n;
     2684    ngx_http_mp4_trak_t *trak, ngx_uint_t start)
     2685{
     2686    uint32_t               start_sample, chunk, samples, id, next_chunk, n,
     2687                           prev_samples;
    25592688    ngx_buf_t             *data, *buf;
    25602689    ngx_uint_t             entries, target_chunk, chunk_samples;
    25612690    ngx_mp4_stsc_entry_t  *entry, *end, *first;
    25622691
     2692    entries = trak->sample_to_chunk_entries - 1;
     2693
     2694    if (start) {
     2695        start_sample = (uint32_t) trak->start_sample;
     2696
     2697    } else if (mp4->length) {
     2698        start_sample = (uint32_t) (trak->end_sample - trak->start_sample);
     2699
     2700        data = trak->out[NGX_HTTP_MP4_STSC_START].buf;
     2701
     2702        if (data) {
     2703            entry = (ngx_mp4_stsc_entry_t *) data->pos;
     2704            samples = ngx_mp4_get_32value(entry->samples);
     2705            entries--;
     2706
     2707            if (samples > start_sample) {
     2708                samples = start_sample;
     2709                ngx_mp4_set_32value(entry->samples, samples);
     2710            }
     2711
     2712            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     2713                           "mp4 stsc using %uD start samples", samples);
     2714
     2715            start_sample -= samples;
     2716        }
     2717
     2718    } else {
     2719        return NGX_OK;
     2720    }
     2721
    25632722    data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf;
    2564 
    2565     start_sample = (uint32_t) trak->start_sample;
    2566     entries = trak->sample_to_chunk_entries - 1;
    25672723
    25682724    entry = (ngx_mp4_stsc_entry_t *) data->pos;
     
    25722728    samples = ngx_mp4_get_32value(entry->samples);
    25732729    id = ngx_mp4_get_32value(entry->id);
     2730    prev_samples = 0;
    25742731    entry++;
    25752732
     
    25912748        start_sample -= n;
    25922749
     2750        prev_samples = samples;
    25932751        chunk = next_chunk;
    25942752        samples = ngx_mp4_get_32value(entry->samples);
     
    26332791                   target_chunk, chunk_samples);
    26342792
    2635     data->pos = (u_char *) entry;
    2636 
    2637     trak->start_chunk = target_chunk;
    2638     trak->chunk_samples = chunk_samples;
    2639 
    2640     ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 1);
    2641 
    2642     samples -= chunk_samples;
     2793    if (start) {
     2794        data->pos = (u_char *) entry;
     2795
     2796        trak->sample_to_chunk_entries = entries;
     2797        trak->start_chunk = target_chunk;
     2798        trak->start_chunk_samples = chunk_samples;
     2799
     2800        ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 1);
     2801
     2802        samples -= chunk_samples;
     2803
     2804    } else {
     2805        if (start_sample) {
     2806            data->last = (u_char *) (entry + 1);
     2807            trak->sample_to_chunk_entries -= entries - 1;
     2808            trak->end_chunk_samples = samples;
     2809
     2810        } else {
     2811            data->last = (u_char *) entry;
     2812            trak->sample_to_chunk_entries -= entries;
     2813            trak->end_chunk_samples = prev_samples;
     2814        }
     2815
     2816        if (chunk_samples) {
     2817            trak->end_chunk = target_chunk + 1;
     2818            trak->end_chunk_samples = chunk_samples;
     2819
     2820        } else {
     2821            trak->end_chunk = target_chunk;
     2822        }
     2823
     2824        samples = chunk_samples;
     2825        next_chunk = chunk + 1;
     2826    }
    26432827
    26442828    if (chunk_samples && next_chunk - target_chunk == 2) {
     
    26462830        ngx_mp4_set_32value(entry->samples, samples);
    26472831
    2648     } else if (chunk_samples) {
    2649 
    2650         first = &trak->stsc_chunk_entry;
     2832    } else if (chunk_samples && start) {
     2833
     2834        first = &trak->stsc_start_chunk_entry;
    26512835        ngx_mp4_set_32value(first->chunk, 1);
    26522836        ngx_mp4_set_32value(first->samples, samples);
    26532837        ngx_mp4_set_32value(first->id, id);
    26542838
    2655         buf = &trak->stsc_chunk_buf;
     2839        buf = &trak->stsc_start_chunk_buf;
    26562840        buf->temporary = 1;
    26572841        buf->pos = (u_char *) first;
    26582842        buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
    26592843
    2660         trak->out[NGX_HTTP_MP4_STSC_CHUNK].buf = buf;
     2844        trak->out[NGX_HTTP_MP4_STSC_START].buf = buf;
    26612845
    26622846        ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 2);
    26632847
    2664         entries++;
    2665     }
    2666 
    2667     trak->sample_to_chunk_entries = entries;
     2848        trak->sample_to_chunk_entries++;
     2849
     2850    } else if (chunk_samples) {
     2851
     2852        first = &trak->stsc_end_chunk_entry;
     2853        ngx_mp4_set_32value(first->chunk, trak->end_chunk - trak->start_chunk);
     2854        ngx_mp4_set_32value(first->samples, samples);
     2855        ngx_mp4_set_32value(first->id, id);
     2856
     2857        buf = &trak->stsc_end_chunk_buf;
     2858        buf->temporary = 1;
     2859        buf->pos = (u_char *) first;
     2860        buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
     2861
     2862        trak->out[NGX_HTTP_MP4_STSC_END].buf = buf;
     2863
     2864        trak->sample_to_chunk_entries++;
     2865    }
    26682866
    26692867    return NGX_OK;
     
    27612959{
    27622960    size_t                atom_size;
    2763     uint32_t             *pos, *end;
     2961    uint32_t             *pos, *end, entries;
    27642962    ngx_buf_t            *atom, *data;
    27652963    ngx_mp4_stsz_atom_t  *stsz_atom;
     
    27772975
    27782976    if (data) {
    2779         if (trak->start_sample > trak->sample_sizes_entries) {
     2977        entries = trak->sample_sizes_entries;
     2978
     2979        if (trak->start_sample > entries) {
    27802980            ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
    27812981                          "start time is out mp4 stsz samples in \"%s\"",
     
    27842984        }
    27852985
     2986        entries -= trak->start_sample;
    27862987        data->pos += trak->start_sample * sizeof(uint32_t);
    27872988        end = (uint32_t *) data->pos;
    27882989
    2789         for (pos = end - trak->chunk_samples; pos < end; pos++) {
    2790             trak->chunk_samples_size += ngx_mp4_get_32value(pos);
     2990        for (pos = end - trak->start_chunk_samples; pos < end; pos++) {
     2991            trak->start_chunk_samples_size += ngx_mp4_get_32value(pos);
    27912992        }
    27922993
    27932994        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
    2794                        "chunk samples sizes:%uL", trak->chunk_samples_size);
     2995                       "chunk samples sizes:%uL",
     2996                       trak->start_chunk_samples_size);
     2997
     2998        if (mp4->length) {
     2999            if (trak->end_sample - trak->start_sample > entries) {
     3000                ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
     3001                              "end time is out mp4 stsz samples in \"%s\"",
     3002                              mp4->file.name.data);
     3003                return NGX_ERROR;
     3004            }
     3005
     3006            entries = trak->end_sample - trak->start_sample;
     3007            data->last = data->pos + entries * sizeof(uint32_t);
     3008            end = (uint32_t *) data->last;
     3009
     3010            for (pos = end - trak->end_chunk_samples; pos < end; pos++) {
     3011                trak->end_chunk_samples_size += ngx_mp4_get_32value(pos);
     3012            }
     3013
     3014            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     3015                           "mp4 stsz end_chunk_samples_size:%uL",
     3016                           trak->end_chunk_samples_size);
     3017        }
    27953018
    27963019        atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos);
     
    28013024
    28023025        ngx_mp4_set_32value(stsz_atom->size, atom_size);
    2803         ngx_mp4_set_32value(stsz_atom->entries,
    2804                             trak->sample_sizes_entries - trak->start_sample);
     3026        ngx_mp4_set_32value(stsz_atom->entries, entries);
    28053027    }
    28063028
     
    28833105{
    28843106    size_t                atom_size;
     3107    uint32_t              entries;
    28853108    ngx_buf_t            *atom, *data;
    28863109    ngx_mp4_stco_atom_t  *stco_atom;
     
    29123135
    29133136    data->pos += trak->start_chunk * sizeof(uint32_t);
     3137
     3138    trak->start_offset = ngx_mp4_get_32value(data->pos);
     3139    trak->start_offset += trak->start_chunk_samples_size;
     3140    ngx_mp4_set_32value(data->pos, trak->start_offset);
     3141
     3142    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     3143                   "start chunk offset:%uD", trak->start_offset);
     3144
     3145    if (mp4->length) {
     3146
     3147        if (trak->end_chunk > trak->chunks) {
     3148            ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
     3149                          "end time is out mp4 stco chunks in \"%s\"",
     3150                          mp4->file.name.data);
     3151            return NGX_ERROR;
     3152        }
     3153
     3154        entries = trak->end_chunk - trak->start_chunk;
     3155        data->last = data->pos + entries * sizeof(uint32_t);
     3156
     3157        if (entries) {
     3158            trak->end_offset =
     3159                            ngx_mp4_get_32value(data->last - sizeof(uint32_t));
     3160            trak->end_offset += trak->end_chunk_samples_size;
     3161
     3162            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     3163                           "end chunk offset:%O", trak->end_offset);
     3164        }
     3165
     3166    } else {
     3167        entries = trak->chunks - trak->start_chunk;
     3168        trak->end_offset = mp4->mdat_data.buf->file_last;
     3169    }
     3170
     3171    if (entries == 0) {
     3172        trak->start_offset = mp4->end;
     3173        trak->end_offset = 0;
     3174    }
     3175
    29143176    atom_size = sizeof(ngx_mp4_stco_atom_t) + (data->last - data->pos);
    29153177    trak->size += atom_size;
    29163178
    2917     trak->start_offset = ngx_mp4_get_32value(data->pos);
    2918     trak->start_offset += trak->chunk_samples_size;
    2919     ngx_mp4_set_32value(data->pos, trak->start_offset);
    2920 
    2921     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
    2922                    "start chunk offset:%uD", trak->start_offset);
    2923 
    29243179    atom = trak->out[NGX_HTTP_MP4_STCO_ATOM].buf;
    29253180    stco_atom = (ngx_mp4_stco_atom_t *) atom->pos;
    29263181
    29273182    ngx_mp4_set_32value(stco_atom->size, atom_size);
    2928     ngx_mp4_set_32value(stco_atom->entries, trak->chunks - trak->start_chunk);
     3183    ngx_mp4_set_32value(stco_atom->entries, entries);
    29293184
    29303185    return NGX_OK;
     
    30343289{
    30353290    size_t                atom_size;
     3291    uint64_t              entries;
    30363292    ngx_buf_t            *atom, *data;
    30373293    ngx_mp4_co64_atom_t  *co64_atom;
     
    30633319
    30643320    data->pos += trak->start_chunk * sizeof(uint64_t);
     3321
     3322    trak->start_offset = ngx_mp4_get_64value(data->pos);
     3323    trak->start_offset += trak->start_chunk_samples_size;
     3324    ngx_mp4_set_64value(data->pos, trak->start_offset);
     3325
     3326    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     3327                   "start chunk offset:%uL", trak->start_offset);
     3328
     3329    if (mp4->length) {
     3330
     3331        if (trak->end_chunk > trak->chunks) {
     3332            ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
     3333                          "end time is out mp4 co64 chunks in \"%s\"",
     3334                          mp4->file.name.data);
     3335            return NGX_ERROR;
     3336        }
     3337
     3338        entries = trak->end_chunk - trak->start_chunk;
     3339        data->last = data->pos + entries * sizeof(uint64_t);
     3340
     3341        if (entries) {
     3342            trak->end_offset =
     3343                            ngx_mp4_get_64value(data->last - sizeof(uint64_t));
     3344            trak->end_offset += trak->end_chunk_samples_size;
     3345
     3346            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
     3347                           "end chunk offset:%O", trak->end_offset);
     3348        }
     3349
     3350    } else {
     3351        entries = trak->chunks - trak->start_chunk;
     3352        trak->end_offset = mp4->mdat_data.buf->file_last;
     3353    }
     3354
     3355    if (entries == 0) {
     3356        trak->start_offset = mp4->end;
     3357        trak->end_offset = 0;
     3358    }
     3359
    30653360    atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos);
    30663361    trak->size += atom_size;
    30673362
    3068     trak->start_offset = ngx_mp4_get_64value(data->pos);
    3069     trak->start_offset += trak->chunk_samples_size;
    3070     ngx_mp4_set_64value(data->pos, trak->start_offset);
    3071 
    3072     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
    3073                    "start chunk offset:%uL", trak->start_offset);
    3074 
    30753363    atom = trak->out[NGX_HTTP_MP4_CO64_ATOM].buf;
    30763364    co64_atom = (ngx_mp4_co64_atom_t *) atom->pos;
    30773365
    30783366    ngx_mp4_set_32value(co64_atom->size, atom_size);
    3079     ngx_mp4_set_32value(co64_atom->entries, trak->chunks - trak->start_chunk);
     3367    ngx_mp4_set_32value(co64_atom->entries, entries);
    30803368
    30813369    return NGX_OK;
Note: See TracChangeset for help on using the changeset viewer.