Mercurial > mplayer.hg
annotate libmpdemux/demux_asf.c @ 33404:7dfe52e4f2e1
Fix play duration calculation error.
Acording to the ASF documentation, the play duration is zero
if the preroll value is greater than the play duration.
The new way of determination (suggested by reimar) prevents
overflows as well.
author | ib |
---|---|
date | Tue, 24 May 2011 13:35:26 +0000 |
parents | 6a6dc18cde26 |
children | 277ec491a8a7 |
rev | line source |
---|---|
29238
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
1 /* |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
2 * ASF file parser for DEMUXER v0.3 |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
3 * copyright (c) 2001 A'rpi/ESP-team |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
4 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
5 * This file is part of MPlayer. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
6 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
7 * MPlayer is free software; you can redistribute it and/or modify |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
8 * it under the terms of the GNU General Public License as published by |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
9 * the Free Software Foundation; either version 2 of the License, or |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
10 * (at your option) any later version. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
11 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
12 * MPlayer is distributed in the hope that it will be useful, |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
15 * GNU General Public License for more details. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
16 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
17 * You should have received a copy of the GNU General Public License along |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
18 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
28051
diff
changeset
|
20 */ |
1 | 21 |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
22 #include <stdio.h> |
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
23 #include <stdlib.h> |
1430 | 24 #include <unistd.h> |
27273 | 25 #include <limits.h> |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
26 |
1567 | 27 #include "config.h" |
28 #include "mp_msg.h" | |
1973
5216f108cb4f
all error/warn/info messages moved to help_mp-en.h for translation
arpi
parents:
1628
diff
changeset
|
29 #include "help_mp.h" |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
30 |
22605
4d81dbdf46b9
Add explicit location for headers from the stream/ directory.
diego
parents:
21968
diff
changeset
|
31 #include "stream/stream.h" |
1342 | 32 #include "asf.h" |
30587
5df7d33f5545
Add header for asf_check_header, read_asf_header; avoids forward declarations.
diego
parents:
30586
diff
changeset
|
33 #include "asfheader.h" |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
34 #include "demuxer.h" |
30586
84a83a93046a
#include proper header for skip_audio_frame() instead of forward declaring it.
diego
parents:
29837
diff
changeset
|
35 #include "libmpcodecs/dec_audio.h" |
17012 | 36 #include "libvo/fastmemcpy.h" |
25488 | 37 #include "libavutil/intreadwrite.h" |
1342 | 38 |
1 | 39 // based on asf file-format doc by Eugene [http://divx.euro.ru] |
40 | |
25487
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
41 /** |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
42 * \brief reads int stored in number of bytes given by len |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
43 * \param ptr pointer to read from, is incremented appropriately |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
44 * \param len lowest 2 bits indicate number of bytes to read |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
45 * \param def default value to return if len is invalid |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
46 */ |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
47 static inline unsigned read_varlen(uint8_t **ptr, int len, int def) { |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
48 const uint8_t *p = *ptr; |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
49 len &= 3; |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
50 switch (len) { |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
51 case 1: *ptr += 1; return *p; |
25488 | 52 case 2: *ptr += 2; return AV_RL16(p); |
53 case 3: *ptr += 4; return AV_RL32(p); | |
25487
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
54 } |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
55 return def; |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
56 } |
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
57 |
25925 | 58 /** |
59 * \brief checks if there is enough data to read the bytes given by len | |
60 * \param ptr pointer to read from | |
61 * \param endptr pointer to the end of the buffer | |
62 * \param len lowest 2 bits indicate number of bytes to read | |
63 */ | |
64 static inline int check_varlen(uint8_t *ptr, uint8_t *endptr, int len) { | |
26414
a7031923e4dc
demux_asf: Fix operator precedence in packet length check
uau
parents:
26069
diff
changeset
|
65 return len&3 ? ptr + (1<<((len&3) - 1)) <= endptr : 1; |
25925 | 66 } |
67 | |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
68 static void asf_descrambling(unsigned char **src,unsigned len, struct asf_priv* asf){ |
27270
44ebd7860248
Make sure demuxed ASF packet is properly padded after descrambling
reimar
parents:
27269
diff
changeset
|
69 unsigned char *dst; |
15553
43af13780751
Speedup asf descrambling (avoid one memcpy and use our fastmemcpy).
reimar
parents:
14502
diff
changeset
|
70 unsigned char *s2=*src; |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
71 unsigned i=0,x,y; |
27282
16beae919ff1
Avoid including avcodec.h in demuxer.h (and thus many other files) just to get
reimar
parents:
27273
diff
changeset
|
72 if (len > UINT_MAX - MP_INPUT_BUFFER_PADDING_SIZE) |
27270
44ebd7860248
Make sure demuxed ASF packet is properly padded after descrambling
reimar
parents:
27269
diff
changeset
|
73 return; |
27282
16beae919ff1
Avoid including avcodec.h in demuxer.h (and thus many other files) just to get
reimar
parents:
27273
diff
changeset
|
74 dst = malloc(len + MP_INPUT_BUFFER_PADDING_SIZE); |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
75 while(len>=asf->scrambling_h*asf->scrambling_w*asf->scrambling_b+i){ |
1567 | 76 // mp_msg(MSGT_DEMUX,MSGL_DBG4,"descrambling! (w=%d b=%d)\n",w,asf_scrambling_b); |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
77 //i+=asf_scrambling_h*asf_scrambling_w; |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
78 for(x=0;x<asf->scrambling_w;x++) |
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
79 for(y=0;y<asf->scrambling_h;y++){ |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
23357
diff
changeset
|
80 fast_memcpy(dst+i,s2+(y*asf->scrambling_w+x)*asf->scrambling_b,asf->scrambling_b); |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
81 i+=asf->scrambling_b; |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
82 } |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
83 s2+=asf->scrambling_h*asf->scrambling_w*asf->scrambling_b; |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
84 } |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
23357
diff
changeset
|
85 //if(i<len) fast_memcpy(dst+i,src+i,len-i); |
15553
43af13780751
Speedup asf descrambling (avoid one memcpy and use our fastmemcpy).
reimar
parents:
14502
diff
changeset
|
86 free(*src); |
43af13780751
Speedup asf descrambling (avoid one memcpy and use our fastmemcpy).
reimar
parents:
14502
diff
changeset
|
87 *src = dst; |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
88 } |
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
89 |
23239 | 90 /***************************************************************** |
91 * \brief initializes asf private data | |
92 * | |
93 */ | |
94 static void init_priv (struct asf_priv* asf){ | |
95 asf->last_vid_seq=-1; | |
96 asf->vid_ext_timing_index=-1; | |
97 asf->aud_ext_timing_index=-1; | |
98 asf->vid_ext_frame_index=-1; | |
99 } | |
100 | |
18609
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
101 static void demux_asf_append_to_packet(demux_packet_t* dp,unsigned char *data,int len,int offs) |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
102 { |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
103 if(dp->len!=offs && offs!=-1) mp_msg(MSGT_DEMUX,MSGL_V,"warning! fragment.len=%d BUT next fragment offset=%d \n",dp->len,offs); |
27282
16beae919ff1
Avoid including avcodec.h in demuxer.h (and thus many other files) just to get
reimar
parents:
27273
diff
changeset
|
104 dp->buffer=realloc(dp->buffer,dp->len+len+MP_INPUT_BUFFER_PADDING_SIZE); |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
23357
diff
changeset
|
105 fast_memcpy(dp->buffer+dp->len,data,len); |
27282
16beae919ff1
Avoid including avcodec.h in demuxer.h (and thus many other files) just to get
reimar
parents:
27273
diff
changeset
|
106 memset(dp->buffer+dp->len+len, 0, MP_INPUT_BUFFER_PADDING_SIZE); |
18609
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
107 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"data appended! %d+%d\n",dp->len,len); |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
108 dp->len+=len; |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
109 } |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
110 |
23239 | 111 static int demux_asf_read_packet(demuxer_t *demux,unsigned char *data,int len,int id,int seq,uint64_t time,unsigned short dur,int offs,int keyframe){ |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
112 struct asf_priv* asf = demux->priv; |
1 | 113 demux_stream_t *ds=NULL; |
18609
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
114 int close_seg=0; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
115 |
1567 | 116 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"demux_asf.read_packet: id=%d seq=%d len=%d\n",id,seq,len); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
117 |
426 | 118 if(demux->video->id==-1) |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
119 if(demux->v_streams[id]) |
426 | 120 demux->video->id=id; |
121 | |
1 | 122 if(demux->audio->id==-1) |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
123 if(demux->a_streams[id]) |
426 | 124 demux->audio->id=id; |
1 | 125 |
126 if(id==demux->audio->id){ | |
127 // audio | |
128 ds=demux->audio; | |
426 | 129 if(!ds->sh){ |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
130 ds->sh=demux->a_streams[id]; |
1567 | 131 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF audio ID = %d\n",ds->id); |
426 | 132 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
133 } else |
1 | 134 if(id==demux->video->id){ |
135 // video | |
136 ds=demux->video; | |
426 | 137 if(!ds->sh){ |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
426
diff
changeset
|
138 ds->sh=demux->v_streams[id]; |
1567 | 139 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF video ID = %d\n",ds->id); |
426 | 140 } |
1 | 141 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
142 |
1 | 143 if(ds){ |
144 if(ds->asf_packet){ | |
18609
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
145 demux_packet_t* dp=ds->asf_packet; |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
146 |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
147 if (ds==demux->video && asf->asf_is_dvr_ms) { |
23239 | 148 if (asf->new_vid_frame_seg) { |
18609
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
149 dp->pos=demux->filepos; |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
150 close_seg = 1; |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
151 } else seq = ds->asf_seq; |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
152 } else close_seg = ds->asf_seq!=seq; |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
153 |
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
154 if(close_seg){ |
1 | 155 // closed segment, finalize packet: |
156 if(ds==demux->audio) | |
18001 | 157 if(asf->scrambling_h>1 && asf->scrambling_w>1 && asf->scrambling_b>0) |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
158 asf_descrambling(&ds->asf_packet->buffer,ds->asf_packet->len,asf); |
1 | 159 ds_add_packet(ds,ds->asf_packet); |
160 ds->asf_packet=NULL; | |
161 } else { | |
162 // append data to it! | |
18609
bb7042d74855
Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
pacman
parents:
18001
diff
changeset
|
163 demux_asf_append_to_packet(dp,data,len,offs); |
1 | 164 // we are ready now. |
165 return 1; | |
166 } | |
167 } | |
168 // create new packet: | |
169 { demux_packet_t* dp; | |
170 if(offs>0){ | |
1567 | 171 mp_msg(MSGT_DEMUX,MSGL_V,"warning! broken fragment, %d bytes missing \n",offs); |
1 | 172 return 0; |
173 } | |
174 dp=new_demux_packet(len); | |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
23357
diff
changeset
|
175 fast_memcpy(dp->buffer,data,len); |
23239 | 176 if (asf->asf_is_dvr_ms) |
23469 | 177 dp->pts=time*0.0000001; |
23239 | 178 else |
23469 | 179 dp->pts=time*0.001; |
979 | 180 dp->flags=keyframe; |
1 | 181 // if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur); |
182 dp->pos=demux->filepos; | |
183 ds->asf_packet=dp; | |
184 ds->asf_seq=seq; | |
185 // we are ready now. | |
186 return 1; | |
187 } | |
188 } | |
189 | |
190 return 0; | |
191 } | |
192 | |
23239 | 193 /***************************************************************** |
194 * \brief read the replicated data associated with each segment | |
195 * \parameter pp reference to replicated data | |
196 * \parameter id stream number | |
197 * \parameter seq media object number | |
198 * \parameter keyframe key frame indicator - set to zero if keyframe, non-zero otherwise | |
199 * \parameter seg_time set to payload time when valid, if audio or new video frame payload, zero otherwise | |
200 * | |
201 */ | |
202 static void get_payload_extension_data(demuxer_t *demux, unsigned char** pp, unsigned char id, unsigned int seq, int *keyframe, uint64_t *seg_time){ | |
203 struct asf_priv* asf = demux->priv; | |
204 uint64_t payload_time; //100ns units | |
205 int i, ext_max, ext_timing_index; | |
206 uint8_t *pi = *pp+4; | |
207 | |
208 if(demux->video->id==-1) | |
209 if(demux->v_streams[id]) | |
210 demux->video->id=id; | |
211 | |
212 if(demux->audio->id==-1) | |
213 if(demux->a_streams[id]) | |
214 demux->audio->id=id; | |
215 | |
216 if (id!=demux->video->id && id!=demux->audio->id) return; | |
217 | |
218 if (id==demux->video->id) { | |
219 ext_max = asf->vid_repdata_count; | |
220 ext_timing_index = asf->vid_ext_timing_index; | |
221 } else { | |
222 ext_max = asf->aud_repdata_count; | |
223 ext_timing_index = asf->aud_ext_timing_index; | |
224 } | |
225 | |
226 *seg_time=0.0; | |
227 asf->new_vid_frame_seg = 0; | |
228 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
229 for (i=0; i<ext_max; i++) { |
23239 | 230 uint16_t payextsize; |
231 uint8_t segment_marker; | |
232 | |
233 if (id==demux->video->id) | |
234 payextsize = asf->vid_repdata_sizes[i]; | |
235 else | |
236 payextsize = asf->aud_repdata_sizes[i]; | |
237 | |
238 if (payextsize == 65535) { | |
25488 | 239 payextsize = AV_RL16(pi); |
23239 | 240 pi+=2; |
241 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
242 |
23239 | 243 // if this is the timing info extension then read the payload time |
244 if (i == ext_timing_index) | |
25488 | 245 payload_time = AV_RL64(pi+8); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
246 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
247 // if this is the video frame info extension then |
23239 | 248 // set the keyframe indicator, the 'new frame segment' indicator |
249 // and (initially) the 'frame time' | |
250 if (i == asf->vid_ext_frame_index && id==demux->video->id) { | |
251 segment_marker = pi[0]; | |
252 // Known video stream segment_marker values that | |
253 // contain useful information: | |
254 // | |
255 // NTSC/ATSC (29.97fps): 0X4A 01001010 | |
256 // 0X4B 01001011 | |
257 // 0X49 01001001 | |
258 // | |
259 // PAL/ATSC (25fps): 0X3A 00111010 | |
260 // 0X3B 00111011 | |
261 // 0X39 00111001 | |
262 // | |
263 // ATSC progressive (29.97fps): 0X7A 01111010 | |
264 // 0X7B 01111011 | |
265 // 0X79 01111001 | |
266 // 11111111 | |
267 // ^ this is new video frame marker | |
268 // | |
269 // ^^^^ these bits indicate the framerate | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
270 // 0X4 is 29.97i, 0X3 is 25i, 0X7 is 29.97p, ???=25p |
23239 | 271 // |
272 // ^^^ these bits indicate the frame type: | |
273 // 001 means I-frame | |
274 // 010 and 011 probably mean P and B | |
275 | |
276 asf->new_vid_frame_seg = (0X08 & segment_marker) && seq != asf->last_vid_seq; | |
277 | |
278 if (asf->new_vid_frame_seg) asf->last_vid_seq = seq; | |
279 | |
280 if (asf->avg_vid_frame_time == 0) { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
281 // set the average frame time initially (in 100ns units). |
23239 | 282 // This is based on what works for known samples. |
283 // It can be extended if more samples of different types can be obtained. | |
284 if (((segment_marker & 0XF0) >> 4) == 4) { | |
285 asf->avg_vid_frame_time = (uint64_t)((1.001 / 30.0) * 10000000.0); | |
286 asf->know_frame_time=1; | |
287 } else if (((segment_marker & 0XF0) >> 4) == 3) { | |
288 asf->avg_vid_frame_time = (uint64_t)(0.04 * 10000000.0); | |
289 asf->know_frame_time=1; | |
290 } else if (((segment_marker & 0XF0) >> 4) == 6) { | |
291 asf->avg_vid_frame_time = (uint64_t)(0.02 * 10000000.0); | |
292 asf->know_frame_time=1; | |
293 } else if (((segment_marker & 0XF0) >> 4) == 7) { | |
294 asf->avg_vid_frame_time = (uint64_t)((1.001 / 60.0) * 10000000.0); | |
295 asf->know_frame_time=1; | |
296 } else { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
297 // we dont know the frame time initially so |
23239 | 298 // make a guess and then recalculate as we go. |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
299 asf->avg_vid_frame_time = (uint64_t)((1.001 / 60.0) * 10000000.0); |
23239 | 300 asf->know_frame_time=0; |
301 } | |
302 } | |
303 *keyframe = (asf->new_vid_frame_seg && (segment_marker & 0X07) == 1); | |
304 } | |
305 pi +=payextsize; | |
306 } | |
307 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
308 if (id==demux->video->id && asf->new_vid_frame_seg) { |
23239 | 309 asf->vid_frame_ct++; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
310 // Some samples only have timings on key frames and |
23239 | 311 // the rest contain non-cronological timestamps. Interpolating |
312 // the values between key frames works for all samples. | |
313 if (*keyframe) { | |
314 asf->found_first_key_frame=1; | |
315 if (!asf->know_frame_time && asf->last_key_payload_time > 0) { | |
316 // We dont know average frametime so recalculate. | |
317 // Giving precedence to the 'weight' of the existing | |
318 // average limits damage done to new value when there is | |
319 // a sudden time jump which happens occasionally. | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
320 asf->avg_vid_frame_time = |
23239 | 321 (0.9 * asf->avg_vid_frame_time) + |
322 (0.1 * ((payload_time - asf->last_key_payload_time) / asf->vid_frame_ct)); | |
323 } | |
324 asf->last_key_payload_time = payload_time; | |
325 asf->vid_frame_ct = 1; | |
326 *seg_time = payload_time; | |
327 } else | |
328 *seg_time = (asf->last_key_payload_time + (asf->avg_vid_frame_time * (asf->vid_frame_ct-1))); | |
329 } | |
330 | |
331 if (id==demux->audio->id) { | |
332 if (payload_time != -1) | |
333 asf->last_aud_diff = payload_time - asf->last_aud_pts; | |
334 asf->last_aud_pts += asf->last_aud_diff; | |
335 *seg_time = asf->last_aud_pts; | |
336 } | |
337 } | |
1 | 338 //static int num_elementary_packets100=0; |
339 //static int num_elementary_packets101=0; | |
340 | |
341 // return value: | |
342 // 0 = EOF or no stream found | |
343 // 1 = successfully read a packet | |
16175 | 344 static int demux_asf_fill_buffer(demuxer_t *demux, demux_stream_t *ds){ |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
345 struct asf_priv* asf = demux->priv; |
1 | 346 |
347 demux->filepos=stream_tell(demux->stream); | |
3475
390388c75209
Applied the patch from Alban Bedel <albeu@free.fr> to
bertrand
parents:
2338
diff
changeset
|
348 // Brodcast stream have movi_start==movi_end |
390388c75209
Applied the patch from Alban Bedel <albeu@free.fr> to
bertrand
parents:
2338
diff
changeset
|
349 // Better test ? |
10622 | 350 if((demux->movi_start < demux->movi_end) && (demux->filepos>=demux->movi_end)){ |
1 | 351 demux->stream->eof=1; |
352 return 0; | |
353 } | |
354 | |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
355 stream_read(demux->stream,asf->packet,asf->packetsize); |
1 | 356 if(demux->stream->eof) return 0; // EOF |
25925 | 357 if(asf->packetsize < 2) return 0; // Packet too short |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
358 |
12877
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
359 { |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
360 unsigned char* p=asf->packet; |
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
361 unsigned char* p_end=asf->packet+asf->packetsize; |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
362 unsigned char flags=p[0]; |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
363 unsigned char segtype=p[1]; |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
364 unsigned padding; |
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
365 unsigned plen; |
33355
6a6dc18cde26
Restore variable that is actually used in debug output.
reimar
parents:
33335
diff
changeset
|
366 unsigned sequence; |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
367 unsigned long time=0; |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
368 unsigned short duration=0; |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
369 |
1 | 370 int segs=1; |
371 unsigned char segsizetype=0x80; | |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
372 int seg=-1; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
373 |
17932 | 374 if( mp_msg_test(MSGT_DEMUX,MSGL_DBG2) ){ |
1 | 375 int i; |
25925 | 376 for(i=0;i<FFMIN(16, asf->packetsize);i++) printf(" %02X",asf->packet[i]); |
1 | 377 printf("\n"); |
378 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
379 |
12877
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
380 // skip ECC data if present by testing bit 7 of flags |
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
381 // 1xxxbbbb -> ecc data present, skip bbbb byte(s) |
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
382 // 0xxxxxxx -> payload parsing info starts |
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
383 if (flags & 0x80) |
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
384 { |
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
385 p += (flags & 0x0f)+1; |
25925 | 386 if (p+1 >= p_end) return 0; // Packet too short |
12877
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
387 flags = p[0]; |
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
388 segtype = p[1]; |
e427e3cc26c1
skip ecc only if present, patch by Alexis Durelle <alexis.durelle@cen.cnamts.fr> (needed for the Aiptek DV3500 camera)
alex
parents:
10832
diff
changeset
|
389 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
390 |
1 | 391 //if(segtype!=0x5d) printf("Warning! packet[4] != 0x5d \n"); |
392 | |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
393 p+=2; // skip flags & segtype |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
394 |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
395 // Read packet size (plen): |
25925 | 396 if(!check_varlen(p, p_end, flags>> 5)) return 0; // Not enough data |
25487
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
397 plen = read_varlen(&p, flags >> 5, 0); |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
398 |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
399 // Read sequence: |
25925 | 400 if(!check_varlen(p, p_end, flags>> 1)) return 0; // Not enough data |
33355
6a6dc18cde26
Restore variable that is actually used in debug output.
reimar
parents:
33335
diff
changeset
|
401 sequence = read_varlen(&p, flags >> 1, 0); |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
402 |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
403 // Read padding size (padding): |
25925 | 404 if(!check_varlen(p, p_end, flags>> 3)) return 0; // Not enough data |
25487
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
405 padding = read_varlen(&p, flags >> 3, 0); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
406 |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
407 if(((flags>>5)&3)!=0){ |
1 | 408 // Explicit (absoulte) packet size |
1567 | 409 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Explicit packet size specified: %d \n",plen); |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
410 if(plen>asf->packetsize) mp_msg(MSGT_DEMUX,MSGL_V,"Warning! plen>packetsize! (%d>%d) \n",plen,asf->packetsize); |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
411 } else { |
1 | 412 // Padding (relative) size |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
413 plen=asf->packetsize-padding; |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
414 } |
1 | 415 |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
416 // Read time & duration: |
25925 | 417 if (p+5 >= p_end) return 0; // Packet too short |
25488 | 418 time = AV_RL32(p); p+=4; |
419 duration = AV_RL16(p); p+=2; | |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
420 |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
421 // Read payload flags: |
1 | 422 if(flags&1){ |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
423 // multiple sub-packets |
25925 | 424 if (p >= p_end) return 0; // Packet too short |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
425 segsizetype=p[0]>>6; |
1 | 426 segs=p[0] & 0x3F; |
427 ++p; | |
428 } | |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
429 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"%08"PRIu64": flag=%02X segs=%d seq=%u plen=%u pad=%u time=%ld dur=%d\n", |
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
430 (uint64_t)demux->filepos,flags,segs,sequence,plen,padding,time,duration); |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
431 |
1 | 432 for(seg=0;seg<segs;seg++){ |
433 //ASF_segmhdr_t* sh; | |
434 unsigned char streamno; | |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
435 unsigned int seq; |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
436 unsigned int x; // offset or timestamp |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
437 unsigned int rlen; |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
438 // |
1 | 439 int len; |
23239 | 440 uint64_t time2=0; |
979 | 441 int keyframe=0; |
1 | 442 |
21968
92f83f7c8eef
Instead of printing a useless "sig11 coming soon" message, just abort parsing
reimar
parents:
20792
diff
changeset
|
443 if(p>=p_end) { |
92f83f7c8eef
Instead of printing a useless "sig11 coming soon" message, just abort parsing
reimar
parents:
20792
diff
changeset
|
444 mp_msg(MSGT_DEMUX,MSGL_V,"Warning! invalid packet 1, aborting parsing...\n"); |
92f83f7c8eef
Instead of printing a useless "sig11 coming soon" message, just abort parsing
reimar
parents:
20792
diff
changeset
|
445 break; |
92f83f7c8eef
Instead of printing a useless "sig11 coming soon" message, just abort parsing
reimar
parents:
20792
diff
changeset
|
446 } |
1 | 447 |
17932 | 448 if( mp_msg_test(MSGT_DEMUX,MSGL_DBG2) ){ |
1 | 449 int i; |
450 printf("seg %d:",seg); | |
25925 | 451 for(i=0;i<FFMIN(16, p_end - p);i++) printf(" %02X",p[i]); |
1 | 452 printf("\n"); |
453 } | |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
454 |
1 | 455 streamno=p[0]&0x7F; |
979 | 456 if(p[0]&0x80) keyframe=1; |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
457 p++; |
1 | 458 |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
459 // Read media object number (seq): |
25925 | 460 if(!check_varlen(p, p_end, segtype >> 4)) break; // Not enough data |
25487
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
461 seq = read_varlen(&p, segtype >> 4, 0); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
462 |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
463 // Read offset or timestamp: |
25925 | 464 if(!check_varlen(p, p_end, segtype >> 2)) break; // Not enough data |
25487
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
465 x = read_varlen(&p, segtype >> 2, 0); |
1 | 466 |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
467 // Read replic.data len: |
25925 | 468 if(!check_varlen(p, p_end, segtype)) break; // Not enough data |
25487
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
469 rlen = read_varlen(&p, segtype, 0); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
470 |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
471 // printf("### rlen=%d \n",rlen); |
32745
64be018ebafa
Check that rlen is valid before using it to increment a pointer.
reimar
parents:
32624
diff
changeset
|
472 if (rlen < 0 || rlen > p_end - p) { |
64be018ebafa
Check that rlen is valid before using it to increment a pointer.
reimar
parents:
32624
diff
changeset
|
473 mp_msg(MSGT_DEMUX, MSGL_V, "invalid rlen=%d\n", rlen); |
64be018ebafa
Check that rlen is valid before using it to increment a pointer.
reimar
parents:
32624
diff
changeset
|
474 break; |
64be018ebafa
Check that rlen is valid before using it to increment a pointer.
reimar
parents:
32624
diff
changeset
|
475 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
476 |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
477 switch(rlen){ |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
478 case 0x01: // 1 = special, means grouping |
1 | 479 //printf("grouping: %02X \n",p[0]); |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
480 ++p; // skip PTS delta |
1 | 481 break; |
482 default: | |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
483 if(rlen>=8){ |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
484 p+=4; // skip object size |
25925 | 485 if (p+3 >= p_end) break; // Packet too short |
25488 | 486 time2=AV_RL32(p); // read PTS |
23239 | 487 if (asf->asf_is_dvr_ms) |
488 get_payload_extension_data(demux, &p, streamno, seq, &keyframe, &time2); | |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
489 p+=rlen-4; |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
490 } else { |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
491 mp_msg(MSGT_DEMUX,MSGL_V,"unknown segment type (rlen): 0x%02X \n",rlen); |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
6668
diff
changeset
|
492 time2=0; // unknown |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
493 p+=rlen; |
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
494 } |
1 | 495 } |
496 | |
497 if(flags&1){ | |
498 // multiple segments | |
25925 | 499 if(!check_varlen(p, p_end, segsizetype)) break; // Not enough data |
25487
81a77832f5fc
Add a read_varlen function to reduce some code duplication
reimar
parents:
23511
diff
changeset
|
500 len = read_varlen(&p, segsizetype, plen-(p-asf->packet)); |
1 | 501 } else { |
502 // single segment | |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
503 len=plen-(p-asf->packet); |
1 | 504 } |
4197 | 505 if(len<0 || (p+len)>p_end){ |
1567 | 506 mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! segment len=%d\n",len); |
27267
62b8f385a0b9
Do not just print a warning, also fix the len in ASF demuxer!
reimar
parents:
27122
diff
changeset
|
507 len = p_end - p; |
1 | 508 } |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
509 mp_dbg(MSGT_DEMUX,MSGL_DBG4," seg #%d: streamno=%d seq=%d type=%02X len=%d\n",seg,streamno,seq,rlen,len); |
1 | 510 |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
511 switch(rlen){ |
1 | 512 case 0x01: |
513 // GROUPING: | |
514 //printf("ASF_parser: warning! grouping (flag=1) not yet supported!\n",len); | |
515 //printf(" total: %d \n",len); | |
516 while(len>0){ | |
517 int len2=p[0]; | |
518 p++; | |
519 //printf(" group part: %d bytes\n",len2); | |
27122
f8df4c3e2ac2
Replace asserts by proper conditions to allow playback of some broken but
reimar
parents:
26612
diff
changeset
|
520 if(len2 > len - 1 || len2 < 0) break; // Not enough data |
f8df4c3e2ac2
Replace asserts by proper conditions to allow playback of some broken but
reimar
parents:
26612
diff
changeset
|
521 len2 = FFMIN(len2, asf->packetsize); |
979 | 522 demux_asf_read_packet(demux,p,len2,streamno,seq,x,duration,-1,keyframe); |
1 | 523 p+=len2; |
524 len-=len2+1; | |
6668 | 525 ++seq; |
1 | 526 } |
527 if(len!=0){ | |
1567 | 528 mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! groups total != len\n"); |
1 | 529 } |
530 break; | |
6442
2eaeb73ce8ab
some cleanup and fixes, but the badquality.asf is still buggy :(
arpi
parents:
4197
diff
changeset
|
531 default: |
1 | 532 // NO GROUPING: |
533 //printf("fragment offset: %d \n",sh->x); | |
27122
f8df4c3e2ac2
Replace asserts by proper conditions to allow playback of some broken but
reimar
parents:
26612
diff
changeset
|
534 if (len <= 0) break; |
26612
87d096a58965
Check ASF packet size before calling demux_asf_read_packet. Fixes segfault
eugeni
parents:
26414
diff
changeset
|
535 if (!asf->asf_is_dvr_ms || asf->found_first_key_frame) { |
27122
f8df4c3e2ac2
Replace asserts by proper conditions to allow playback of some broken but
reimar
parents:
26612
diff
changeset
|
536 len = FFMIN(len, asf->packetsize); |
23239 | 537 demux_asf_read_packet(demux,p,len,streamno,seq,time2,duration,x,keyframe); |
26612
87d096a58965
Check ASF packet size before calling demux_asf_read_packet. Fixes segfault
eugeni
parents:
26414
diff
changeset
|
538 } |
1 | 539 p+=len; |
540 break; | |
541 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
542 |
1 | 543 } // for segs |
544 return 1; // success | |
545 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
546 |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
547 mp_msg(MSGT_DEMUX,MSGL_V,"%08"PRIX64": UNKNOWN TYPE %02X %02X %02X %02X %02X...\n",(int64_t)demux->filepos,asf->packet[0],asf->packet[1],asf->packet[2],asf->packet[3],asf->packet[4]); |
1 | 548 return 0; |
549 } | |
1466 | 550 |
551 #include "stheader.h" | |
552 | |
17636 | 553 static void demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){ |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
554 struct asf_priv* asf = demuxer->priv; |
1466 | 555 demux_stream_t *d_audio=demuxer->audio; |
556 demux_stream_t *d_video=demuxer->video; | |
557 sh_audio_t *sh_audio=d_audio->sh; | |
558 // sh_video_t *sh_video=d_video->sh; | |
559 | |
560 //FIXME: OFF_T - didn't test ASF case yet (don't have a large asf...) | |
561 //FIXME: reports good or bad to steve@daviesfam.org please | |
562 | |
563 //================= seek in ASF ========================== | |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
564 float p_rate=asf->packetrate; // packets / sec |
25883
baf32110d3fc
Use defines to give names to the different seek flags.
reimar
parents:
25707
diff
changeset
|
565 off_t rel_seek_packs=(flags&SEEK_FACTOR)? // FIXME: int may be enough? |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
566 (rel_seek_secs*(demuxer->movi_end-demuxer->movi_start)/asf->packetsize): |
1628
bd1ef18cdf33
seeking flags implemented: 0x1=rel/abs and 0x2=time/percent
arpi
parents:
1567
diff
changeset
|
567 (rel_seek_secs*p_rate); |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
568 off_t rel_seek_bytes=rel_seek_packs*asf->packetsize; |
1466 | 569 off_t newpos; |
570 //printf("ASF: packs: %d duration: %d \n",(int)fileh.packets,*((int*)&fileh.duration)); | |
571 // printf("ASF_seek: %d secs -> %d packs -> %d bytes \n", | |
572 // rel_seek_secs,rel_seek_packs,rel_seek_bytes); | |
25883
baf32110d3fc
Use defines to give names to the different seek flags.
reimar
parents:
25707
diff
changeset
|
573 newpos=((flags&SEEK_ABSOLUTE)?demuxer->movi_start:demuxer->filepos)+rel_seek_bytes; |
1466 | 574 if(newpos<0 || newpos<demuxer->movi_start) newpos=demuxer->movi_start; |
575 // printf("\r -- asf: newpos=%d -- \n",newpos); | |
576 stream_seek(demuxer->stream,newpos); | |
577 | |
19961
9f011e6892e8
interpolate real fps of dvr-ms files using the extended stream properties.
nicodvb
parents:
18710
diff
changeset
|
578 if (asf->asf_is_dvr_ms) asf->dvr_last_vid_pts = 0.0f; |
9f011e6892e8
interpolate real fps of dvr-ms files using the extended stream properties.
nicodvb
parents:
18710
diff
changeset
|
579 |
13310
c629f7ac9b9f
fix seeking in audio-only case (crash when seeking backwards, time reset to 0)
reimar
parents:
12877
diff
changeset
|
580 if (d_video->id >= 0) |
1466 | 581 ds_fill_buffer(d_video); |
582 if(sh_audio){ | |
583 ds_fill_buffer(d_audio); | |
584 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
585 |
18710
c528c6c518f1
Clean up audio pts handling, make audio pts tracking in the audio-only
uau
parents:
18609
diff
changeset
|
586 if (d_video->id >= 0) |
1466 | 587 while(1){ |
588 if(sh_audio && !d_audio->eof){ | |
589 float a_pts=d_audio->pts; | |
590 a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; | |
591 // sync audio: | |
592 if (d_video->pts > a_pts){ | |
593 skip_audio_frame(sh_audio); | |
594 // if(!ds_fill_buffer(d_audio)) sh_audio=NULL; // skip audio. EOF? | |
595 continue; | |
596 } | |
597 } | |
598 if(d_video->flags&1) break; // found a keyframe! | |
599 if(!ds_fill_buffer(d_video)) break; // skip frame. EOF? | |
600 } | |
601 | |
602 | |
603 } | |
604 | |
16175 | 605 static int demux_asf_control(demuxer_t *demuxer,int cmd, void *arg){ |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
606 struct asf_priv* asf = demuxer->priv; |
8254
772d6d27fd66
warning patch by (Dominik Mierzejewski <dominik at rangers dot eu dot org>)
michael
parents:
8208
diff
changeset
|
607 /* demux_stream_t *d_audio=demuxer->audio; |
8208
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
608 demux_stream_t *d_video=demuxer->video; |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
609 sh_audio_t *sh_audio=d_audio->sh; |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
610 sh_video_t *sh_video=d_video->sh; |
8254
772d6d27fd66
warning patch by (Dominik Mierzejewski <dominik at rangers dot eu dot org>)
michael
parents:
8208
diff
changeset
|
611 */ |
8208
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
612 switch(cmd) { |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
613 case DEMUXER_CTRL_GET_TIME_LENGTH: |
29837 | 614 *((double *)arg)=asf->movielength; |
8208
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
615 return DEMUXER_CTRL_OK; |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
616 |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
617 case DEMUXER_CTRL_GET_PERCENT_POS: |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
618 return DEMUXER_CTRL_DONTKNOW; |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
619 |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
620 default: |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
621 return DEMUXER_CTRL_NOTIMPL; |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
622 } |
ae5a2ae1c349
demuxer_control(), percent position and time length query implemented in
arpi
parents:
8123
diff
changeset
|
623 } |
16175 | 624 |
625 | |
626 static demuxer_t* demux_open_asf(demuxer_t* demuxer) | |
627 { | |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
628 struct asf_priv* asf = demuxer->priv; |
16175 | 629 sh_video_t *sh_video=NULL; |
630 | |
631 //---- ASF header: | |
17992
2545bbd91450
Move global vars used for header parsing, etc to dewux->priv as it should
albeu
parents:
17932
diff
changeset
|
632 if(!asf) return NULL; |
23239 | 633 init_priv(asf); |
23295 | 634 if (!read_asf_header(demuxer,asf)) |
17598
4b8193d51bda
we cannot continue without a crash when read_asf_header fails, since some
reimar
parents:
17569
diff
changeset
|
635 return NULL; |
16175 | 636 stream_reset(demuxer->stream); |
637 stream_seek(demuxer->stream,demuxer->movi_start); | |
638 // demuxer->idx_pos=0; | |
639 // demuxer->endpos=avi_header.movi_end; | |
640 if(demuxer->video->id != -2) { | |
641 if(!ds_fill_buffer(demuxer->video)){ | |
642 mp_msg(MSGT_DEMUXER,MSGL_WARN,"ASF: " MSGTR_MissingVideoStream); | |
643 demuxer->video->sh=NULL; | |
644 //printf("ASF: missing video stream!? contact the author, it may be a bug :(\n"); | |
645 } else { | |
32599
b8afc497ccd3
Remove useless assignment already done in new_sh_video.
reimar
parents:
32598
diff
changeset
|
646 sh_video=demuxer->video->sh; |
23239 | 647 sh_video->fps=1000.0f; sh_video->frametime=0.001f; |
20636
325db3f2aba3
don't set the resolution for dvr-ms files: in the asf headers it seems to
nicodvb
parents:
19961
diff
changeset
|
648 |
325db3f2aba3
don't set the resolution for dvr-ms files: in the asf headers it seems to
nicodvb
parents:
19961
diff
changeset
|
649 if (asf->asf_is_dvr_ms) { |
325db3f2aba3
don't set the resolution for dvr-ms files: in the asf headers it seems to
nicodvb
parents:
19961
diff
changeset
|
650 sh_video->bih->biWidth = 0; |
325db3f2aba3
don't set the resolution for dvr-ms files: in the asf headers it seems to
nicodvb
parents:
19961
diff
changeset
|
651 sh_video->bih->biHeight = 0; |
325db3f2aba3
don't set the resolution for dvr-ms files: in the asf headers it seems to
nicodvb
parents:
19961
diff
changeset
|
652 } |
16175 | 653 } |
654 } | |
655 | |
656 if(demuxer->audio->id!=-2){ | |
657 mp_msg(MSGT_DEMUXER,MSGL_V,MSGTR_ASFSearchingForAudioStream,demuxer->audio->id); | |
658 if(!ds_fill_buffer(demuxer->audio)){ | |
659 mp_msg(MSGT_DEMUXER,MSGL_INFO,"ASF: " MSGTR_MissingAudioStream); | |
660 demuxer->audio->sh=NULL; | |
661 } | |
662 } | |
20792
dcaf8b9f47e9
Fix crash when attempting to seek in a streamed unseekable stream, like
gpoirier
parents:
20636
diff
changeset
|
663 if(!demuxer->stream->seek) |
dcaf8b9f47e9
Fix crash when attempting to seek in a streamed unseekable stream, like
gpoirier
parents:
20636
diff
changeset
|
664 demuxer->seekable=0; |
16175 | 665 |
666 return demuxer; | |
667 } | |
668 | |
669 | |
23239 | 670 static void demux_close_asf(demuxer_t *demuxer) { |
671 struct asf_priv* asf = demuxer->priv; | |
672 | |
673 if (!asf) return; | |
674 | |
32537
8fa2f43cb760
Remove most of the NULL pointer check before free all over the code
cboesch
parents:
30587
diff
changeset
|
675 free(asf->aud_repdata_sizes); |
8fa2f43cb760
Remove most of the NULL pointer check before free all over the code
cboesch
parents:
30587
diff
changeset
|
676 free(asf->vid_repdata_sizes); |
32624 | 677 free(asf->packet); |
23239 | 678 free(asf); |
679 } | |
680 | |
25707
d4fe6e23283e
Make all demuxer_desc_t const, thus moving them to .rodata
reimar
parents:
25488
diff
changeset
|
681 const demuxer_desc_t demuxer_desc_asf = { |
16175 | 682 "ASF demuxer", |
17232
d318e2ff799e
Typo in ASF demuxer selection by name (it's 'asf', not 'asv')
rtognimp
parents:
17226
diff
changeset
|
683 "asf", |
16175 | 684 "ASF", |
685 "A'rpi", | |
686 "ASF, WMV, WMA", | |
687 DEMUXER_TYPE_ASF, | |
688 1, // safe autodetect | |
689 asf_check_header, | |
690 demux_asf_fill_buffer, | |
691 demux_open_asf, | |
23239 | 692 demux_close_asf, |
16175 | 693 demux_seek_asf, |
694 demux_asf_control | |
695 }; |