Rev 6106 | Rev 6118 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6106 | Rev 6117 | ||
---|---|---|---|
Line 23... | Line 23... | ||
23 | 23 | ||
Line 24... | Line 24... | ||
24 | void decoder(); |
24 | void decoder(); |
25 | int fplay_init_context(AVCodecContext *avctx); |
25 | int fplay_init_context(AVCodecContext *avctx); |
Line 26... | Line -... | ||
26 | - | ||
27 | AVFormatContext *pFormatCtx; |
- | |
28 | AVCodecContext *pCodecCtx; |
- | |
29 | AVCodecContext *aCodecCtx; |
- | |
30 | AVCodec *pCodec; |
- | |
31 | AVCodec *aCodec; |
26 | |
32 | AVFrame *pFrame; |
- | |
33 | int videoStream; |
- | |
Line 34... | Line 27... | ||
34 | int audioStream; |
27 | AVFrame *pFrame; |
Line 35... | Line 28... | ||
35 | 28 | ||
36 | int have_sound = 0; |
29 | int have_sound = 0; |
Line 42... | Line 35... | ||
42 | char *movie_file; |
35 | char *movie_file; |
43 | 36 | ||
Line 44... | Line 37... | ||
44 | void flush_video(); |
37 | void flush_video(); |
Line 45... | Line -... | ||
45 | - | ||
46 | queue_t q_video; |
- | |
- | 38 | ||
47 | queue_t q_audio; |
39 | |
Line 48... | Line 40... | ||
48 | int64_t rewind_pos; |
40 | int64_t rewind_pos; |
Line 49... | Line 41... | ||
49 | 41 | ||
Line 50... | Line 42... | ||
50 | int64_t stream_duration; |
42 | int64_t stream_duration; |
Line -... | Line 43... | ||
- | 43 | ||
51 | 44 | int threads_running = DECODER_THREAD; |
|
52 | int threads_running = DECODER_THREAD; |
45 | |
53 | 46 | extern double audio_base; |
|
54 | extern double audio_base; |
47 | |
Line 55... | Line 48... | ||
55 | 48 | ||
56 | double get_audio_base() |
49 | double get_audio_base(vst_t* vst) |
- | 50 | { |
|
57 | { |
51 | return (double)av_q2d(vst->fCtx->streams[vst->aStream]->time_base)*1000; |
58 | return (double)av_q2d(pFormatCtx->streams[audioStream]->time_base)*1000; |
52 | }; |
Line 59... | Line 53... | ||
59 | }; |
53 | |
60 | 54 | ||
61 | 55 | int main( int argc, char *argv[]) |
|
Line 82... | Line 76... | ||
82 | avcodec_register_all(); |
76 | avcodec_register_all(); |
83 | avdevice_register_all(); |
77 | avdevice_register_all(); |
84 | av_register_all(); |
78 | av_register_all(); |
Line 85... | Line 79... | ||
85 | 79 | ||
86 | if( avformat_open_input(&pFormatCtx, movie_file, NULL, NULL) < 0) |
80 | if( avformat_open_input(&vst.fCtx, movie_file, NULL, NULL) < 0) |
87 | { |
81 | { |
88 | printf("Cannot open file %s\n\r", movie_file); |
82 | printf("Cannot open file %s\n\r", movie_file); |
89 | return -1; // Couldn't open file |
83 | return -1; // Couldn't open file |
Line 90... | Line 84... | ||
90 | }; |
84 | }; |
Line 91... | Line 85... | ||
91 | 85 | ||
92 | pFormatCtx->flags |= AVFMT_FLAG_GENPTS; |
86 | vst.fCtx->flags |= AVFMT_FLAG_GENPTS; |
93 | 87 | ||
94 | // Retrieve stream information |
88 | // Retrieve stream information |
95 | if(avformat_find_stream_info(pFormatCtx, NULL)<0) |
89 | if(avformat_find_stream_info(vst.fCtx, NULL) < 0) |
96 | { |
90 | { |
Line 107... | Line 101... | ||
107 | movie_file[dot-file_name] = 0; |
101 | movie_file[dot-file_name] = 0; |
108 | } |
102 | } |
109 | else movie_file = file_name; |
103 | else movie_file = file_name; |
110 | 104 | ||
Line 111... | Line 105... | ||
111 | stream_duration = pFormatCtx->duration; |
105 | stream_duration = vst.fCtx->duration; |
Line 112... | Line 106... | ||
112 | 106 | ||
113 | // Find the first video stream |
107 | // Find the first video stream |
114 | videoStream=-1; |
108 | vst.vStream = -1; |
- | 109 | vst.aStream = -1; |
|
115 | audioStream=-1; |
110 | |
116 | for(i=0; i < pFormatCtx->nb_streams; i++) |
111 | for(i=0; i < vst.fCtx->nb_streams; i++) |
117 | { |
112 | { |
118 | if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO |
113 | if(vst.fCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO |
119 | && videoStream < 0) |
114 | && vst.vStream < 0) |
120 | { |
115 | { |
121 | videoStream=i; |
116 | vst.vStream = i; |
122 | video_time_base = pFormatCtx->streams[i]->time_base; |
117 | video_time_base = vst.fCtx->streams[i]->time_base; |
123 | if(stream_duration == 0) |
118 | if(stream_duration == 0) |
124 | stream_duration = pFormatCtx->streams[i]->duration; |
- | |
125 | 119 | stream_duration = vst.fCtx->streams[i]->duration; |
|
- | 120 | } |
|
126 | } |
121 | |
127 | if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO && |
122 | if(vst.fCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO && |
128 | audioStream < 0) |
123 | vst.aStream < 0) |
129 | { |
124 | { |
130 | audioStream=i; |
125 | vst.aStream = i; |
131 | if(stream_duration == 0) |
126 | if(stream_duration == 0) |
132 | stream_duration = pFormatCtx->streams[i]->duration; |
127 | stream_duration = vst.fCtx->streams[i]->duration; |
133 | } |
128 | } |
Line 134... | Line 129... | ||
134 | } |
129 | } |
135 | 130 | ||
136 | if(videoStream==-1) |
131 | if(vst.vStream==-1) |
137 | { |
132 | { |
138 | printf("Video stream not detected\n\r"); |
133 | printf("Video stream not detected\n\r"); |
Line 139... | Line 134... | ||
139 | return -1; // Didn't find a video stream |
134 | return -1; // Didn't find a video stream |
Line 140... | Line 135... | ||
140 | }; |
135 | }; |
141 | 136 | ||
142 | // __asm__ __volatile__("int3"); |
137 | // __asm__ __volatile__("int3"); |
143 | - | ||
144 | // Get a pointer to the codec context for the video stream |
- | |
145 | pCodecCtx = pFormatCtx->streams[videoStream]->codec; |
- | |
146 | aCodecCtx = pFormatCtx->streams[audioStream]->codec; |
- | |
147 | - | ||
Line -... | Line 138... | ||
- | 138 | ||
- | 139 | // Get a pointer to the codec context for the video stream |
|
148 | // Find the decoder for the video stream |
140 | vst.vCtx = vst.fCtx->streams[vst.vStream]->codec; |
Line 149... | Line 141... | ||
149 | 141 | vst.aCtx = vst.fCtx->streams[vst.aStream]->codec; |
|
- | 142 | ||
150 | 143 | vst.vCodec = avcodec_find_decoder(vst.vCtx->codec_id); |
|
151 | pCodec=avcodec_find_decoder(pCodecCtx->codec_id); |
144 | printf("codec id %x name %s\n",vst.vCtx->codec_id, vst.vCodec->name); |
152 | 145 | printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt); |
|
153 | // printf("ctx->pix_fmt %d\n", pCodecCtx->pix_fmt); |
146 | |
Line -... | Line 147... | ||
- | 147 | if(vst.vCodec == NULL) |
|
- | 148 | { |
|
- | 149 | printf("Unsupported codec with id %d for input stream %d\n", |
|
154 | 150 | vst.vCtx->codec_id, vst.vStream); |
|
155 | if(pCodec==NULL) { |
151 | return -1; // Codec not found |
156 | printf("Unsupported codec with id %d for input stream %d\n", |
152 | } |
157 | pCodecCtx->codec_id, videoStream); |
153 | |
158 | return -1; // Codec not found |
154 | |
159 | } |
155 | |
Line 160... | Line -... | ||
160 | - | ||
Line 161... | Line 156... | ||
161 | if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0) |
156 | |
162 | { |
157 | if(avcodec_open2(vst.vCtx, vst.vCodec, NULL) < 0) |
- | 158 | { |
|
Line 163... | Line 159... | ||
163 | printf("Error while opening codec for input stream %d\n", |
159 | printf("Error while opening codec for input stream %d\n", |
164 | videoStream); |
160 | vst.vStream); |
165 | return -1; // Could not open codec |
161 | return -1; // Could not open codec |
166 | }; |
162 | }; |
Line 167... | Line 163... | ||
167 | 163 | ||
Line 168... | Line 164... | ||
168 | // printf("ctx->pix_fmt %d\n", pCodecCtx->pix_fmt); |
164 | |
169 | 165 | mutex_init(&vst.q_video.lock); |
|
170 | mutex_init(&q_video.lock); |
166 | mutex_init(&vst.q_audio.lock); |
171 | mutex_init(&q_audio.lock); |
167 | mutex_init(&vst.gpu_lock); |
172 | 168 | ||
173 | if (aCodecCtx->channels > 0) |
169 | if (vst.aCtx->channels > 0) |
174 | aCodecCtx->request_channels = FFMIN(2, aCodecCtx->channels); |
170 | vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels); |
Line 175... | Line 171... | ||
175 | else |
171 | else |
176 | aCodecCtx->request_channels = 2; |
172 | vst.aCtx->request_channels = 2; |
177 | 173 | ||
178 | aCodec = avcodec_find_decoder(aCodecCtx->codec_id); |
174 | vst.aCodec = avcodec_find_decoder(vst.aCtx->codec_id); |
179 | 175 | ||
180 | if(aCodec) |
176 | if(vst.aCodec) |
181 | { |
177 | { |
182 | if(avcodec_open2(aCodecCtx, aCodec, NULL) >= 0 ) |
178 | if(avcodec_open2(vst.aCtx, vst.aCodec, NULL) >= 0 ) |
Line 183... | Line 179... | ||
183 | { |
179 | { |
Line 184... | Line 180... | ||
184 | WAVEHEADER whdr; |
180 | WAVEHEADER whdr; |
Line 185... | Line 181... | ||
185 | int fmt; |
181 | int fmt; |
186 | int channels; |
182 | int channels; |
Line 220... | Line 216... | ||
220 | else printf("Cannot open audio codec\n\r"); |
216 | else printf("Cannot open audio codec\n\r"); |
221 | } |
217 | } |
222 | else printf("Unsupported audio codec!\n"); |
218 | else printf("Unsupported audio codec!\n"); |
223 | 219 | ||
Line 224... | Line 220... | ||
224 | if( !init_video(pCodecCtx)) |
220 | if(!init_video(&vst)) |
225 | return 0; |
221 | return 0; |
Line 226... | Line 222... | ||
226 | 222 | ||
Line 227... | Line 223... | ||
227 | decoder(); |
223 | decoder(&vst); |
228 | 224 | ||
Line 238... | Line 234... | ||
238 | 234 | ||
Line 239... | Line 235... | ||
239 | if(astream.lock.handle) |
235 | if(astream.lock.handle) |
240 | mutex_destroy(&astream.lock); |
236 | mutex_destroy(&astream.lock); |
Line 241... | Line 237... | ||
241 | 237 | ||
242 | mutex_destroy(&q_video.lock); |
238 | mutex_destroy(&vst.q_video.lock); |
Line 243... | Line 239... | ||
243 | mutex_destroy(&q_audio.lock); |
239 | mutex_destroy(&vst.q_audio.lock); |
244 | 240 | ||
Line 245... | Line 241... | ||
245 | return 0; |
241 | return 0; |
246 | } |
242 | } |
247 | 243 | ||
248 | 244 | ||
Line 249... | Line 245... | ||
249 | static int load_frame() |
245 | static int load_frame(vst_t *vst) |
250 | { |
246 | { |
251 | AVPacket packet; |
247 | AVPacket packet; |
252 | int err; |
248 | int err; |
253 | 249 | ||
254 | err = av_read_frame(pFormatCtx, &packet); |
250 | err = av_read_frame(vst->fCtx, &packet); |
255 | if( err == 0) |
251 | if( err == 0) |
256 | { |
252 | { |
257 | if(packet.stream_index==videoStream) |
253 | if(packet.stream_index == vst->vStream) |
258 | put_packet(&q_video, &packet); |
254 | put_packet(&vst->q_video, &packet); |
259 | else if( (packet.stream_index == audioStream) && |
255 | else if( (packet.stream_index == vst->aStream) && |
260 | (have_sound != 0) ) |
256 | (have_sound != 0) ) |
261 | { |
257 | { |
262 | put_packet(&q_audio, &packet); |
258 | put_packet(&vst->q_audio, &packet); |
263 | if(audio_base == -1.0) |
259 | if(audio_base == -1.0) |
264 | { |
260 | { |
265 | if (packet.pts != AV_NOPTS_VALUE) |
261 | if (packet.pts != AV_NOPTS_VALUE) |
266 | audio_base = get_audio_base() * packet.pts; |
262 | audio_base = get_audio_base(vst) * packet.pts; |
Line 276... | Line 272... | ||
276 | } |
272 | } |
277 | 273 | ||
Line 278... | Line 274... | ||
278 | 274 | ||
279 | 275 | ||
280 | static int fill_queue() |
276 | static int fill_queue(vst_t* vst) |
281 | { |
277 | { |
Line 282... | Line 278... | ||
282 | int err = 0; |
278 | int err = 0; |
283 | AVPacket packet; |
- | |
284 | 279 | AVPacket packet; |
|
Line 285... | Line 280... | ||
285 | while( (q_video.size < 4*1024*1024) && |
280 | |
286 | !err ) |
- | |
287 | err = load_frame(); |
281 | while( (vst->q_video.size < 4*1024*1024) && !err ) |
Line 288... | Line 282... | ||
288 | 282 | err = load_frame(vst); |
|
289 | return err; |
283 | |
290 | 284 | return err; |
|
Line 291... | Line 285... | ||
291 | }; |
285 | }; |
292 | 286 | ||
293 | 287 | ||
294 | static void flush_all() |
288 | static void flush_all(vst_t* vst) |
Line 295... | Line 289... | ||
295 | { |
289 | { |
296 | AVPacket packet; |
290 | AVPacket packet; |
Line 297... | Line 291... | ||
297 | 291 | ||
Line 298... | Line 292... | ||
298 | avcodec_flush_buffers(pCodecCtx); |
292 | avcodec_flush_buffers(vst->vCtx); |
299 | avcodec_flush_buffers(aCodecCtx); |
293 | avcodec_flush_buffers(vst->aCtx); |
Line 300... | Line 294... | ||
300 | while( get_packet(&q_video, &packet) != 0) |
294 | while( get_packet(&vst->q_video, &packet) != 0) |
301 | av_free_packet(&packet); |
295 | av_free_packet(&packet); |
302 | 296 | ||
303 | while( get_packet(&q_audio, &packet)!= 0) |
297 | while( get_packet(&vst->q_audio, &packet)!= 0) |
304 | av_free_packet(&packet); |
298 | av_free_packet(&packet); |
Line 324... | Line 318... | ||
324 | 318 | ||
Line 325... | Line 319... | ||
325 | switch(decoder_state) |
319 | switch(decoder_state) |
326 | { |
320 | { |
327 | case PREPARE: |
321 | case PREPARE: |
328 | eof = fill_queue(); |
322 | eof = fill_queue(vst); |
Line 329... | Line 323... | ||
329 | 323 | ||
330 | do |
324 | do |
331 | { |
325 | { |
332 | if( (q_video.size < 4*1024*1024) && |
326 | if( (vst->q_video.size < 4*1024*1024) && |
333 | (eof == 0) ) |
327 | (eof == 0) ) |
334 | { |
328 | { |
335 | eof = load_frame(); |
329 | eof = load_frame(vst); |
336 | } |
330 | } |
337 | decode_video(pCodecCtx, &q_video); |
331 | decode_video(vst); |
338 | ret = decode_audio(aCodecCtx, &q_audio); |
332 | ret = decode_audio(vst->aCtx, &vst->q_audio); |
339 | }while(astream.count < resampler_size*2 && |
333 | }while(astream.count < resampler_size*2 && |
Line 340... | Line 334... | ||
340 | ret == 1); |
334 | ret == 1); |
341 | 335 | ||
342 | sound_state = PREPARE; |
336 | sound_state = PREPARE; |
Line 343... | Line 337... | ||
343 | decoder_state = PLAY; |
337 | decoder_state = PLAY; |
344 | player_state = PLAY; |
338 | player_state = PLAY; |
345 | 339 | ||
346 | case PLAY: |
340 | case PLAY: |
347 | if( (q_video.size < 4*1024*1024) && |
341 | if( (vst->q_video.size < 4*1024*1024) && |
348 | (eof == 0) ) |
342 | (eof == 0) ) |
349 | { |
343 | { |
350 | eof = load_frame(); |
344 | eof = load_frame(vst); |
351 | } |
345 | } |
Line 352... | Line 346... | ||
352 | vret = decode_video(pCodecCtx, &q_video); |
346 | vret = decode_video(vst); |
353 | aret = decode_audio(aCodecCtx, &q_audio); |
347 | aret = decode_audio(vst->aCtx, &vst->q_audio); |
354 | ret = vret | aret; |
348 | ret = vret | aret; |
355 | 349 | ||
356 | if( eof && !ret) |
350 | if( eof && !ret) |
Line 357... | Line 351... | ||
357 | { |
351 | { |
358 | decoder_state = STOP; |
352 | decoder_state = STOP; |
359 | continue; |
353 | continue; |
360 | }; |
354 | }; |
361 | 355 | ||
362 | if( (vret & aret) == -1) |
356 | if( (vret & aret) == -1) |
363 | { |
357 | { |
364 | if( (q_video.size < 4*1024*1024) && |
358 | if( (vst->q_video.size < 4*1024*1024) && |
365 | (eof == 0) ) |
359 | (eof == 0) ) |
366 | { |
360 | { |
367 | eof = load_frame(); |
361 | eof = load_frame(vst); |
Line 383... | Line 377... | ||
383 | case PLAY_2_STOP: |
377 | case PLAY_2_STOP: |
384 | while(sound_state != STOP) |
378 | while(sound_state != STOP) |
385 | delay(1); |
379 | delay(1); |
Line 386... | Line 380... | ||
386 | 380 | ||
Line 387... | Line 381... | ||
387 | flush_all(); |
381 | flush_all(vst); |
388 | 382 | ||
389 | if (pFormatCtx->start_time != AV_NOPTS_VALUE) |
383 | if (vst->fCtx->start_time != AV_NOPTS_VALUE) |
390 | rewind_pos = pFormatCtx->start_time; |
384 | rewind_pos = vst->fCtx->start_time; |
Line 391... | Line 385... | ||
391 | else |
385 | else |
392 | rewind_pos = 0; |
386 | rewind_pos = 0; |
Line 393... | Line 387... | ||
393 | 387 | ||
394 | ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN, |
388 | ret = avformat_seek_file(vst->fCtx, -1, INT64_MIN, |
Line 395... | Line 389... | ||
395 | rewind_pos, INT64_MAX, 0); |
389 | rewind_pos, INT64_MAX, 0); |
396 | 390 | ||
397 | decoder_state = STOP; |
391 | decoder_state = STOP; |
Line 398... | Line 392... | ||
398 | break; |
392 | break; |
399 | 393 | ||
400 | case REWIND: |
394 | case REWIND: |
401 | while(sound_state != STOP) |
395 | while(sound_state != STOP) |
402 | yield(); |
396 | yield(); |
403 | 397 | ||
404 | flush_all(); |
398 | flush_all(vst); |
Line 405... | Line 399... | ||
405 | int opts = 0; |
399 | int opts = 0; |
406 | if(rewind_pos < 0) |
400 | if(rewind_pos < 0) |
Line 407... | Line 401... | ||
407 | { |
401 | { |
408 | rewind_pos = -rewind_pos; |
402 | rewind_pos = -rewind_pos; |
409 | opts = AVSEEK_FLAG_BACKWARD; |
403 | opts = AVSEEK_FLAG_BACKWARD; |
Line 410... | Line 404... | ||
410 | }; |
404 | }; |
411 | 405 | ||
412 | if (pFormatCtx->start_time != AV_NOPTS_VALUE) |
- | |
413 | rewind_pos += pFormatCtx->start_time; |
406 | if (vst->fCtx->start_time != AV_NOPTS_VALUE) |
414 | 407 | rewind_pos += vst->fCtx->start_time; |
|
415 | // printf("rewind %8"PRId64"\n", rewind_pos); |
408 | |
416 | min_pos = rewind_pos - 1000000; |
409 | // printf("rewind %8"PRId64"\n", rewind_pos); |
417 | max_pos = rewind_pos + 1000000; |
410 | min_pos = rewind_pos - 1000000; |
418 | - | ||
419 | ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN, |
- | |
420 | rewind_pos, INT64_MAX, 0); |
411 | max_pos = rewind_pos + 1000000; |
421 | 412 | ||
422 | if (ret < 0) |
413 | ret = avformat_seek_file(vst->fCtx, -1, INT64_MIN, |
423 | { |
414 | rewind_pos, INT64_MAX, 0); |
424 | printf("could not seek to position %f\n", |
- | |
425 | (double)rewind_pos / AV_TIME_BASE); |
415 | if (ret < 0) |