Rev 6133 | Rev 6144 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4438 | Serge | 1 | |
2 | |||
3 | |||
4 | #include |
||
5 | #include |
||
6 | #include |
||
7 | |||
8 | |||
9 | #include |
||
10 | #include |
||
11 | #include |
||
12 | #include |
||
13 | #include "winlib/winlib.h" |
||
5021 | Serge | 14 | |
4438 | Serge | 15 | |
16 | #include "fplay.h" |
||
17 | |||
18 | |||
19 | volatile enum player_state decoder_state = PREPARE; |
||
20 | volatile enum player_state sound_state = STOP; |
||
21 | |||
22 | |||
23 | |||
24 | |||
6136 | serge | 25 | |
4438 | Serge | 26 | |
6121 | serge | 27 | extern int resampler_size; |
4438 | Serge | 28 | extern int sample_rate; |
29 | |||
30 | |||
31 | |||
32 | |||
33 | |||
34 | |||
5603 | serge | 35 | |
36 | |||
4438 | Serge | 37 | |
38 | |||
6117 | serge | 39 | |
4438 | Serge | 40 | { |
41 | static vst_t vst; |
||
6117 | serge | 42 | int i, ret; |
43 | char *file_name, *dot; |
||
4438 | Serge | 44 | |
45 | |||
46 | { |
||
47 | vst.input_file = get_moviefile(); |
||
6136 | serge | 48 | if(vst.input_file == NULL) |
49 | { |
||
4438 | Serge | 50 | printf("Please provide a movie file\n"); |
51 | return -1; |
||
52 | } |
||
53 | } |
||
54 | else vst.input_file = argv[1]; |
||
6136 | serge | 55 | |
4438 | Serge | 56 | |
57 | |||
58 | |||
59 | |||
60 | |||
61 | avdevice_register_all(); |
||
62 | av_register_all(); |
||
63 | |||
64 | |||
6136 | serge | 65 | { |
4438 | Serge | 66 | printf("Cannot open file %s\n\r", vst.input_file); |
6136 | serge | 67 | return -1; // Couldn't open file |
4438 | Serge | 68 | }; |
69 | |||
70 | |||
6117 | serge | 71 | |
4438 | Serge | 72 | |
73 | if(avformat_find_stream_info(vst.fCtx, NULL) < 0) |
||
6117 | serge | 74 | { |
4438 | Serge | 75 | printf("Cannot find streams\n\r"); |
76 | return -1; |
||
77 | }; |
||
78 | |||
79 | |||
6136 | serge | 80 | dot = strrchr(file_name,'.'); |
4438 | Serge | 81 | if(dot) |
82 | { |
||
83 | vst.input_name = malloc(dot-file_name+1); |
||
6136 | serge | 84 | memcpy(vst.input_name, file_name, dot-file_name); |
85 | vst.input_name[dot-file_name] = 0; |
||
86 | } |
||
4438 | Serge | 87 | else vst.input_name = file_name; |
6136 | serge | 88 | |
4438 | Serge | 89 | |
6117 | serge | 90 | |
4438 | Serge | 91 | |
92 | vst.vStream = -1; |
||
6117 | serge | 93 | vst.aStream = -1; |
94 | |||
95 | |||
96 | { |
||
4438 | Serge | 97 | if(vst.fCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO |
6117 | serge | 98 | && vst.vStream < 0) |
99 | { |
||
4438 | Serge | 100 | vst.vStream = i; |
6117 | serge | 101 | vst.video_time_base = vst.fCtx->streams[i]->time_base; |
6136 | serge | 102 | if(stream_duration == 0) |
4438 | Serge | 103 | stream_duration = vst.fCtx->streams[i]->duration; |
6117 | serge | 104 | } |
105 | |||
4438 | Serge | 106 | |
6117 | serge | 107 | vst.aStream < 0) |
108 | { |
||
4438 | Serge | 109 | vst.aStream = i; |
6117 | serge | 110 | vst.audio_time_base = vst.fCtx->streams[i]->time_base; |
6136 | serge | 111 | if(stream_duration == 0) |
4438 | Serge | 112 | stream_duration = vst.fCtx->streams[i]->duration; |
6117 | serge | 113 | } |
4438 | Serge | 114 | } |
115 | |||
116 | |||
6117 | serge | 117 | { |
4438 | Serge | 118 | printf("Video stream not detected\n\r"); |
119 | return -1; // Didn't find a video stream |
||
120 | }; |
||
121 | |||
122 | |||
123 | |||
124 | |||
125 | vst.vCtx = vst.fCtx->streams[vst.vStream]->codec; |
||
6117 | serge | 126 | vst.aCtx = vst.fCtx->streams[vst.aStream]->codec; |
127 | |||
4438 | Serge | 128 | |
6117 | serge | 129 | |
4438 | Serge | 130 | |
6133 | serge | 131 | INIT_LIST_HEAD(&vst.output_list); |
132 | mutex_init(&vst.q_video.lock); |
||
133 | mutex_init(&vst.q_audio.lock); |
||
134 | mutex_init(&vst.gpu_lock); |
||
135 | mutex_init(&vst.decoder_lock); |
||
136 | mutex_init(&vst.input_lock); |
||
137 | mutex_init(&vst.output_lock); |
||
138 | |||
139 | |||
6117 | serge | 140 | { |
141 | printf("Unsupported codec with id %d for input stream %d\n", |
||
4438 | Serge | 142 | vst.vCtx->codec_id, vst.vStream); |
6117 | serge | 143 | return -1; |
6136 | serge | 144 | } |
4438 | Serge | 145 | |
146 | |||
6136 | serge | 147 | if(vst.Frame == NULL) |
148 | { |
||
149 | printf("Cannot alloc video frame\n"); |
||
150 | return -1; |
||
151 | }; |
||
152 | |||
153 | |||
6121 | serge | 154 | return -1; |
155 | |||
6117 | serge | 156 | |
157 | { |
||
4438 | Serge | 158 | printf("Error while opening codec for input stream %d\n", |
159 | vst.vStream); |
||
6117 | serge | 160 | return -1; // Could not open codec |
4438 | Serge | 161 | }; |
162 | |||
163 | |||
6117 | serge | 164 | vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels); |
165 | else |
||
4438 | Serge | 166 | vst.aCtx->request_channels = 2; |
6117 | serge | 167 | |
4438 | Serge | 168 | |
6117 | serge | 169 | |
4438 | Serge | 170 | |
6117 | serge | 171 | { |
4438 | Serge | 172 | if(avcodec_open2(vst.aCtx, vst.aCodec, NULL) >= 0 ) |
6117 | serge | 173 | { |
4438 | Serge | 174 | WAVEHEADER whdr; |
175 | int fmt; |
||
176 | int channels; |
||
177 | |||
178 | |||
179 | vst.aCtx->sample_rate, vst.aCtx->channels, vst.aCtx->sample_fmt ); |
||
6117 | serge | 180 | whdr.riff_id = 0x46464952; |
4438 | Serge | 181 | whdr.riff_format = 0x45564157; |
182 | whdr.wFormatTag = 0x01; |
||
183 | whdr.nSamplesPerSec = vst.aCtx->sample_rate; |
||
6117 | serge | 184 | whdr.nChannels = 2; |
4438 | Serge | 185 | whdr.wBitsPerSample = 16; |
186 | |||
187 | |||
6117 | serge | 188 | |
4438 | Serge | 189 | |
190 | |||
191 | |||
192 | { |
||
193 | decoder_buffer = (uint8_t*)av_mallocz(192000*2+64); |
||
194 | if( decoder_buffer != NULL ) |
||
195 | { |
||
196 | mutex_init(&astream.lock); |
||
5603 | serge | 197 | astream.count = 0; |
4438 | Serge | 198 | astream.buffer = (char *)av_mallocz(192000*3); |
199 | if( astream.buffer != NULL ) |
||
200 | have_sound = 1; |
||
201 | else |
||
202 | av_free(decoder_buffer); |
||
203 | } |
||
204 | if( have_sound == 0) |
||
205 | { |
||
206 | printf("Not enough memory for audio buffers\n"); |
||
207 | } |
||
208 | } |
||
209 | } |
||
210 | else printf("Cannot open audio codec\n\r"); |
||
211 | } |
||
212 | else printf("Unsupported audio codec!\n"); |
||
213 | |||
214 | |||
6136 | serge | 215 | create_thread(video_thread, &vst, 1024*1024); |
216 | if(mutex_lock_timeout(&vst.decoder_lock, 3000) == 0) |
||
217 | return -1; |
||
218 | |||
4438 | Serge | 219 | |
6117 | serge | 220 | |
4438 | Serge | 221 | |
222 | |||
223 | |||
224 | |||
5603 | serge | 225 | (AUDIO_THREAD | VIDEO_THREAD)) |
226 | delay(1); |
||
227 | |||
4438 | Serge | 228 | |
5603 | serge | 229 | mutex_destroy(&astream.lock); |
230 | |||
4438 | Serge | 231 | |
6117 | serge | 232 | mutex_destroy(&vst.q_audio.lock); |
233 | mutex_destroy(&vst.decoder_lock); |
||
6133 | serge | 234 | return 0; |
4438 | Serge | 235 | } |
236 | |||
237 | |||
238 | |||
6117 | serge | 239 | { |
4438 | Serge | 240 | AVPacket packet; |
241 | int err; |
||
242 | |||
243 | |||
6117 | serge | 244 | if( err == 0) |
4438 | Serge | 245 | { |
246 | if(packet.stream_index == vst->vStream) |
||
6117 | serge | 247 | put_packet(&vst->q_video, &packet); |
248 | else if( (packet.stream_index == vst->aStream) && |
||
249 | (have_sound != 0) ) |
||
4438 | Serge | 250 | { |
251 | put_packet(&vst->q_audio, &packet); |
||
6117 | serge | 252 | if(audio_base == -1.0) |
4438 | Serge | 253 | { |
254 | if (packet.pts != AV_NOPTS_VALUE) |
||
255 | audio_base = get_audio_base(vst) * packet.pts; |
||
6117 | serge | 256 | // printf("audio base %f\n", audio_base); |
4438 | Serge | 257 | }; |
258 | } |
||
259 | else av_free_packet(&packet); |
||
260 | } |
||
261 | else if (err != AVERROR_EOF) |
||
262 | printf("av_read_frame: error %x\n", err); |
||
263 | |||
264 | |||
265 | } |
||
266 | |||
267 | |||
268 | |||
269 | |||
6117 | serge | 270 | { |
4438 | Serge | 271 | int err = 0; |
272 | AVPacket packet; |
||
273 | |||
274 | |||
6117 | serge | 275 | err = load_frame(vst); |
276 | |||
4438 | Serge | 277 | |
278 | }; |
||
279 | |||
280 | |||
281 | |||
6117 | serge | 282 | { |
4438 | Serge | 283 | AVPacket packet; |
284 | |||
285 | |||
6117 | serge | 286 | avcodec_flush_buffers(vst->aCtx); |
287 | while( get_packet(&vst->q_video, &packet) != 0) |
||
288 | av_free_packet(&packet); |
||
4438 | Serge | 289 | |
290 | |||
6117 | serge | 291 | av_free_packet(&packet); |
4438 | Serge | 292 | |
293 | |||
6118 | serge | 294 | |
4438 | Serge | 295 | |
296 | }; |
||
297 | |||
298 | |||
6117 | serge | 299 | { |
4438 | Serge | 300 | int eof; |
301 | AVPacket packet; |
||
302 | int ret, vret, aret; |
||
303 | |||
304 | |||
305 | |||
306 | |||
5592 | serge | 307 | |
308 | |||
4438 | Serge | 309 | { |
310 | int err; |
||
311 | |||
312 | |||
313 | { |
||
314 | case PREPARE: |
||
315 | eof = fill_queue(vst); |
||
6117 | serge | 316 | |
4438 | Serge | 317 | |
318 | { |
||
319 | if( (vst->q_video.size < 4*1024*1024) && |
||
6117 | serge | 320 | (eof == 0) ) |
4438 | Serge | 321 | { |
322 | eof = load_frame(vst); |
||
6117 | serge | 323 | } |
4438 | Serge | 324 | decode_video(vst); |
6117 | serge | 325 | ret = decode_audio(vst->aCtx, &vst->q_audio); |
326 | }while(astream.count < resampler_size*2 && ret == 1); |
||
6133 | serge | 327 | |
4438 | Serge | 328 | |
329 | decoder_state = PLAY; |
||
330 | player_state = PLAY; |
||
331 | |||
332 | |||
333 | if( (vst->q_video.size < 4*1024*1024) && |
||
6117 | serge | 334 | (eof == 0) ) |
4438 | Serge | 335 | { |
336 | eof = load_frame(vst); |
||
6117 | serge | 337 | } |
4438 | Serge | 338 | vret = decode_video(vst); |
6117 | serge | 339 | aret = decode_audio(vst->aCtx, &vst->q_audio); |
340 | ret = vret | aret; |
||
4438 | Serge | 341 | |
342 | |||
343 | { |
||
344 | decoder_state = STOP; |
||
345 | continue; |
||
346 | }; |
||
347 | |||
348 | |||
349 | { |
||
350 | if( (vst->q_video.size < 4*1024*1024) && |
||
6117 | serge | 351 | (eof == 0) ) |
4438 | Serge | 352 | { |
353 | eof = load_frame(vst); |
||
6117 | serge | 354 | yield(); |
4438 | Serge | 355 | continue; |
356 | }; |
||
357 | delay(1); |
||
358 | continue; |
||
359 | } |
||
360 | yield(); |
||
361 | continue; |
||
362 | |||
363 | |||
364 | delay(1); |
||
365 | continue; |
||
366 | |||
367 | |||
368 | |||
369 | while(sound_state != STOP) |
||
370 | delay(1); |
||
371 | |||
372 | |||
6117 | serge | 373 | |
4438 | Serge | 374 | |
6117 | serge | 375 | rewind_pos = vst->fCtx->start_time; |
376 | else |
||
4438 | Serge | 377 | rewind_pos = 0; |
378 | |||
379 | |||
6117 | serge | 380 | rewind_pos, INT64_MAX, 0); |
4438 | Serge | 381 | |
382 | |||
383 | break; |
||
384 | |||
385 | |||
386 | while(sound_state != STOP) |
||
387 | yield(); |
||
388 | |||
389 | |||
6117 | serge | 390 | int opts = 0; |
4438 | Serge | 391 | if(rewind_pos < 0) |
392 | { |
||
393 | rewind_pos = -rewind_pos; |
||
394 | opts = AVSEEK_FLAG_BACKWARD; |
||
395 | }; |
||
396 | |||
397 | |||
6117 | serge | 398 | rewind_pos += vst->fCtx->start_time; |
399 | |||
4438 | Serge | 400 | |
401 | min_pos = rewind_pos - 1000000; |
||
402 | max_pos = rewind_pos + 1000000; |
||
403 | |||
404 | |||
6117 | serge | 405 | rewind_pos, INT64_MAX, 0); |
4438 | Serge | 406 | if (ret < 0) |
407 | { |
||
408 | printf("could not seek to position %f\n", |
||
409 | (double)rewind_pos / AV_TIME_BASE); |
||
410 | } |
||
411 | decoder_state = PREPARE; |
||
412 | break; |
||
413 | } |
||
414 | }; |
||
415 | };>>>>>>>>>>>>>> |
||
416 |