00001 #include "qtffthread.h"
00002 #include "qtffutil.h"
00003
00004 qtffthread::qtffthread()
00005 {
00006 }
00007
00008 qtffthread::~qtffthread()
00009 {
00010 EXIT_INPUT_THREAD=1;
00011 wait();
00012 }
00013
00014 void qtffthread::init(VideoState *is)
00015 {
00016 is->parse_tid = SDL_CreateThread(decode_thread, is);
00017 if (!is->parse_tid) {
00018 av_free(is);
00019
00020 }
00021
00022 }
00023
00024 void qtffthread::togglePause()
00025 {
00026
00027
00028 SDL_Event evt;
00029 evt.type = SDL_KEYDOWN;
00030 evt.key.keysym.sym = SDLK_SPACE;
00031 while ( SDL_PushEvent( &evt ) == -1) {}
00032 }
00033
00034
00035
00036
00037
00038
00039
00040 void qtffthread::run()
00041 {
00042 SDL_Event event;
00043 double incr, pos, frac;
00044 while (!EXIT_INPUT_THREAD)
00045 {
00046 SDL_WaitEvent(&event);
00047 switch(event.type) {
00048 case SDL_KEYDOWN:
00049 switch(event.key.keysym.sym) {
00050 case SDLK_ESCAPE:
00051 case SDLK_q:
00052 do_exit();
00053 break;
00054 case SDLK_f:
00055 toggle_full_screen();
00056 break;
00057 case SDLK_p:
00058 case SDLK_SPACE:
00059 toggle_pause();
00060 break;
00061 case SDLK_s:
00062 step_to_next_frame();
00063 break;
00064 case SDLK_a:
00065 if (cur_stream)
00066 stream_cycle_channel(cur_stream, CODEC_TYPE_AUDIO);
00067 break;
00068 case SDLK_v:
00069 if (cur_stream)
00070 stream_cycle_channel(cur_stream, CODEC_TYPE_VIDEO);
00071 break;
00072 case SDLK_t:
00073 if (cur_stream)
00074 stream_cycle_channel(cur_stream, CODEC_TYPE_SUBTITLE);
00075 break;
00076 case SDLK_w:
00077 toggle_audio_display();
00078 break;
00079 case SDLK_LEFT:
00080 incr = -10.0;
00081 goto do_seek;
00082 case SDLK_RIGHT:
00083 incr = 10.0;
00084 goto do_seek;
00085 case SDLK_UP:
00086 incr = 60.0;
00087 goto do_seek;
00088 case SDLK_DOWN:
00089 incr = -60.0;
00090 do_seek:
00091 if (cur_stream) {
00092 pos = get_master_clock(cur_stream);
00093 pos += incr;
00094 stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
00095 }
00096 break;
00097 default:
00098 break;
00099 }
00100 break;
00101 case SDL_MOUSEBUTTONDOWN:
00102 if (cur_stream) {
00103 int ns, hh, mm, ss;
00104 int tns, thh, tmm, tss;
00105 tns = cur_stream->ic->duration/1000000LL;
00106 thh = tns/3600;
00107 tmm = (tns%3600)/60;
00108 tss = (tns%60);
00109 frac = (double)event.button.x/(double)cur_stream->width;
00110 ns = frac*tns;
00111 hh = ns/3600;
00112 mm = (ns%3600)/60;
00113 ss = (ns%60);
00114 fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
00115 hh, mm, ss, thh, tmm, tss);
00116 stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
00117 }
00118 break;
00119 case SDL_VIDEORESIZE:
00120 if (cur_stream) {
00121 myscreen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
00122 SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
00123 cur_stream->width = event.resize.w;
00124 cur_stream->height = event.resize.h;
00125 }
00126 break;
00127 case SDL_QUIT:
00128 case FF_QUIT_EVENT:
00129 do_exit();
00130 break;
00131 case FF_ALLOC_EVENT:
00132 alloc_picture(event.user.data1);
00133 break;
00134 case FF_REFRESH_EVENT:
00135 video_refresh_timer(event.user.data1);
00136 break;
00137 default:
00138 break;
00139 }
00140 }
00141 }
00142
00143 void qtffthread::do_exit(void)
00144 {
00145 EXIT_INPUT_THREAD=1;
00146
00147 if (cur_stream) {
00148 stream_close(cur_stream);
00149 cur_stream = NULL;
00150 }
00151 if (show_status)
00152 printf("\n");
00153 SDL_Quit();
00154 exit(0);
00155 }
00156
00157 void qtffthread::toggle_full_screen(void)
00158 {
00159 int w, h, flags;
00160 is_full_screen = !is_full_screen;
00161 if (!fs_screen_width) {
00162
00163 SDL_WM_ToggleFullScreen(myscreen);
00164 } else {
00165
00166 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
00167 if (is_full_screen) {
00168 w = fs_screen_width;
00169 h = fs_screen_height;
00170 flags |= SDL_FULLSCREEN;
00171 } else {
00172 w = screen_width;
00173 h = screen_height;
00174 flags |= SDL_RESIZABLE;
00175 }
00176 myscreen = SDL_SetVideoMode(w, h, 0, flags);
00177 cur_stream->width = w;
00178 cur_stream->height = h;
00179 }
00180 }
00181
00182 void qtffthread::toggle_pause(void)
00183 {
00184 if (cur_stream)
00185 stream_pause(cur_stream);
00186 step = 0;
00187 }
00188
00189 void qtffthread::stream_cycle_channel(VideoState *is, int codec_type)
00190 {
00191 AVFormatContext *ic = is->ic;
00192 int start_index, stream_index;
00193 AVStream *st;
00194
00195 if (codec_type == CODEC_TYPE_VIDEO)
00196 start_index = is->video_stream;
00197 else if (codec_type == CODEC_TYPE_AUDIO)
00198 start_index = is->audio_stream;
00199 else
00200 start_index = is->subtitle_stream;
00201 if (start_index < (codec_type == CODEC_TYPE_SUBTITLE ? -1 : 0))
00202 return;
00203 stream_index = start_index;
00204 for(;;) {
00205 if (++stream_index >= is->ic->nb_streams)
00206 {
00207 if (codec_type == CODEC_TYPE_SUBTITLE)
00208 {
00209 stream_index = -1;
00210 goto the_end;
00211 } else
00212 stream_index = 0;
00213 }
00214 if (stream_index == start_index)
00215 return;
00216 st = ic->streams[stream_index];
00217 if (st->codec->codec_type == codec_type) {
00218
00219 switch(codec_type) {
00220 case CODEC_TYPE_AUDIO:
00221 if (st->codec->sample_rate != 0 &&
00222 st->codec->channels != 0)
00223 goto the_end;
00224 break;
00225 case CODEC_TYPE_VIDEO:
00226 case CODEC_TYPE_SUBTITLE:
00227 goto the_end;
00228 default:
00229 break;
00230 }
00231 }
00232 }
00233 the_end:
00234 stream_component_close(is, start_index);
00235 stream_component_open(is, stream_index);
00236 }
00237
00238
00239
00240
00241 void qtffthread::step_to_next_frame(void)
00242 {
00243 if (cur_stream) {
00244 if (cur_stream->paused)
00245 cur_stream->paused=0;
00246 cur_stream->video_current_pts = get_video_clock(cur_stream);
00247 }
00248 step = 1;
00249 }
00250
00251
00252 void qtffthread::toggle_audio_display(void)
00253 {
00254 if (cur_stream) {
00255 cur_stream->show_audio = !cur_stream->show_audio;
00256 }
00257 }
00258
00259
00260 void qtffthread::stream_seek(VideoState *is, int64_t pos, int rel)
00261 {
00262 if (!is->seek_req) {
00263 is->seek_pos = pos;
00264 is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
00265 is->seek_req = 1;
00266 }
00267 }
00268
00269
00270
00271 void qtffthread::alloc_picture(void *opaque)
00272 {
00273 VideoState *is = (VideoState*)opaque;
00274 VideoPicture *vp;
00275
00276 vp = &is->pictq[is->pictq_windex];
00277
00278 if (vp->bmp)
00279 SDL_FreeYUVOverlay(vp->bmp);
00280
00281 vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
00282 is->video_st->codec->height,
00283 SDL_YV12_OVERLAY,
00284 myscreen);
00285 vp->width = is->video_st->codec->width;
00286 vp->height = is->video_st->codec->height;
00287
00288 SDL_LockMutex(is->pictq_mutex);
00289 vp->allocated = 1;
00290 SDL_CondSignal(is->pictq_cond);
00291 SDL_UnlockMutex(is->pictq_mutex);
00292 }
00293
00294
00295 void qtffthread::video_refresh_timer(void *opaque)
00296 {
00297 VideoState *is = (VideoState*)opaque;
00298 VideoPicture *vp;
00299 double actual_delay, delay, sync_threshold, ref_clock, diff;
00300
00301 SubPicture *sp, *sp2;
00302
00303 if (is->video_st) {
00304 if (is->pictq_size == 0) {
00305
00306 schedule_refresh(is, 1);
00307 } else {
00308
00309 vp = &is->pictq[is->pictq_rindex];
00310
00311
00312 is->video_current_pts = vp->pts;
00313 is->video_current_pts_time = av_gettime();
00314
00315
00316 delay = vp->pts - is->frame_last_pts;
00317 if (delay <= 0 || delay >= 1.0) {
00318
00319 delay = is->frame_last_delay;
00320 }
00321 is->frame_last_delay = delay;
00322 is->frame_last_pts = vp->pts;
00323
00324
00325 if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
00326 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
00327
00328
00329 ref_clock = get_master_clock(is);
00330 diff = vp->pts - ref_clock;
00331
00332
00333
00334
00335 sync_threshold = AV_SYNC_THRESHOLD;
00336 if (delay > sync_threshold)
00337 sync_threshold = delay;
00338 if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
00339 if (diff <= -sync_threshold)
00340 delay = 0;
00341 else if (diff >= sync_threshold)
00342 delay = 2 * delay;
00343 }
00344 }
00345
00346 is->frame_timer += delay;
00347
00348
00349 actual_delay = is->frame_timer - (av_gettime() / 1000000.0);
00350 if (actual_delay < 0.010) {
00351
00352 actual_delay = 0.010;
00353 }
00354
00355 schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));
00356
00357 #if defined(DEBUG_SYNC)
00358 printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",
00359 delay, actual_delay, vp->pts, -diff);
00360 #endif
00361
00362 if(is->subtitle_st) {
00363 if (is->subtitle_stream_changed) {
00364 SDL_LockMutex(is->subpq_mutex);
00365
00366 while (is->subpq_size) {
00367 free_subpicture(&is->subpq[is->subpq_rindex]);
00368
00369
00370 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
00371 is->subpq_rindex = 0;
00372
00373 is->subpq_size--;
00374 }
00375 is->subtitle_stream_changed = 0;
00376
00377 SDL_CondSignal(is->subpq_cond);
00378 SDL_UnlockMutex(is->subpq_mutex);
00379 } else {
00380 if (is->subpq_size > 0) {
00381 sp = &is->subpq[is->subpq_rindex];
00382
00383 if (is->subpq_size > 1)
00384 sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE];
00385 else
00386 sp2 = NULL;
00387
00388 if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000)))
00389 || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000))))
00390 {
00391 free_subpicture(sp);
00392
00393
00394 if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE)
00395 is->subpq_rindex = 0;
00396
00397 SDL_LockMutex(is->subpq_mutex);
00398 is->subpq_size--;
00399 SDL_CondSignal(is->subpq_cond);
00400 SDL_UnlockMutex(is->subpq_mutex);
00401 }
00402 }
00403 }
00404 }
00405
00406
00407 video_display(is);
00408
00409
00410 if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
00411 is->pictq_rindex = 0;
00412
00413 SDL_LockMutex(is->pictq_mutex);
00414 is->pictq_size--;
00415 SDL_CondSignal(is->pictq_cond);
00416 SDL_UnlockMutex(is->pictq_mutex);
00417 }
00418 } else if (is->audio_st) {
00419
00420
00421 schedule_refresh(is, 40);
00422
00423
00424
00425
00426
00427 video_display(is);
00428 } else {
00429 schedule_refresh(is, 100);
00430 }
00431 if (show_status) {
00432 static int64_t last_time;
00433 int64_t cur_time;
00434 int aqsize, vqsize, sqsize;
00435 double av_diff;
00436
00437 cur_time = av_gettime();
00438 if (!last_time || (cur_time - last_time) >= 500 * 1000) {
00439 aqsize = 0;
00440 vqsize = 0;
00441 sqsize = 0;
00442 if (is->audio_st)
00443 aqsize = is->audioq.size;
00444 if (is->video_st)
00445 vqsize = is->videoq.size;
00446 if (is->subtitle_st)
00447 sqsize = is->subtitleq.size;
00448 av_diff = 0;
00449 if (is->audio_st && is->video_st)
00450 av_diff = get_audio_clock(is) - get_video_clock(is);
00451 printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB sq=%5dB \r",
00452 get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024, sqsize);
00453 fflush(stdout);
00454 last_time = cur_time;
00455 }
00456 }
00457 }
00458
00459 void qtffthread::free_subpicture(SubPicture *sp)
00460 {
00461 int i;
00462
00463 for (i = 0; i < sp->sub.num_rects; i++)
00464 {
00465 av_free(sp->sub.rects[i].bitmap);
00466 av_free(sp->sub.rects[i].rgba_palette);
00467 }
00468
00469 av_free(sp->sub.rects);
00470
00471 memset(&sp->sub, 0, sizeof(AVSubtitle));
00472 }
00473
00474
00475 void qtffthread::schedule_refresh(VideoState *is, int delay)
00476 {
00477 SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
00478 }
00479
00480
00481 void qtffthread::video_display(VideoState *is)
00482 {
00483 if (is->audio_st && is->show_audio)
00484 video_audio_display(is);
00485 else if (is->video_st)
00486 video_image_display(is);
00487 }
00488 void qtffthread::stream_close(VideoState *is)
00489 {
00490 VideoPicture *vp;
00491 int i;
00492
00493 is->abort_request = 1;
00494 SDL_WaitThread(is->parse_tid, NULL);
00495
00496
00497 for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
00498 vp = &is->pictq[i];
00499 if (vp->bmp) {
00500 SDL_FreeYUVOverlay(vp->bmp);
00501 vp->bmp = NULL;
00502 }
00503 }
00504 SDL_DestroyMutex(is->pictq_mutex);
00505 SDL_DestroyCond(is->pictq_cond);
00506 SDL_DestroyMutex(is->subpq_mutex);
00507 SDL_DestroyCond(is->subpq_cond);
00508 SDL_DestroyMutex(is->subtitle_decoder_mutex);
00509 SDL_DestroyMutex(is->audio_decoder_mutex);
00510 SDL_DestroyMutex(is->video_decoder_mutex);
00511 }
00512
00513 void qtffthread::video_audio_display(VideoState *s)
00514 {
00515 int i, i_start, x, y1, y, ys, delay, n, nb_display_channels;
00516 int ch, channels, h, h2, bgcolor, fgcolor;
00517 int16_t time_diff;
00518
00519
00520 channels = s->audio_st->codec->channels;
00521 nb_display_channels = channels;
00522 if (!s->paused) {
00523 n = 2 * channels;
00524 delay = audio_write_get_buf_size(s);
00525 delay /= n;
00526
00527
00528
00529 if (audio_callback_time) {
00530 time_diff = av_gettime() - audio_callback_time;
00531 delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000;
00532 }
00533
00534 delay -= s->width / 2;
00535 if (delay < s->width)
00536 delay = s->width;
00537 i_start = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
00538 s->last_i_start = i_start;
00539 } else {
00540 i_start = s->last_i_start;
00541 }
00542
00543 bgcolor = SDL_MapRGB(myscreen->format, 0x00, 0x00, 0x00);
00544 fill_rectangle(myscreen,
00545 s->xleft, s->ytop, s->width, s->height,
00546 bgcolor);
00547
00548 fgcolor = SDL_MapRGB(myscreen->format, 0xff, 0xff, 0xff);
00549
00550
00551 h = s->height / nb_display_channels;
00552
00553 h2 = (h * 9) / 20;
00554 for(ch = 0;ch < nb_display_channels; ch++) {
00555 i = i_start + ch;
00556 y1 = s->ytop + ch * h + (h / 2);
00557 for(x = 0; x < s->width; x++) {
00558 y = (s->sample_array[i] * h2) >> 15;
00559 if (y < 0) {
00560 y = -y;
00561 ys = y1 - y;
00562 } else {
00563 ys = y1;
00564 }
00565 fill_rectangle(myscreen,
00566 s->xleft + x, ys, 1, y,
00567 fgcolor);
00568 i += channels;
00569 if (i >= SAMPLE_ARRAY_SIZE)
00570 i -= SAMPLE_ARRAY_SIZE;
00571 }
00572 }
00573
00574 fgcolor = SDL_MapRGB(myscreen->format, 0x00, 0x00, 0xff);
00575
00576 for(ch = 1;ch < nb_display_channels; ch++) {
00577 y = s->ytop + ch * h;
00578 fill_rectangle(myscreen,
00579 s->xleft, y, s->width, 1,
00580 fgcolor);
00581 }
00582 SDL_UpdateRect(myscreen, s->xleft, s->ytop, s->width, s->height);
00583 }
00584
00585 void qtffthread::video_image_display(VideoState *is)
00586 {
00587 VideoPicture *vp;
00588 SubPicture *sp;
00589 AVPicture pict;
00590 float aspect_ratio;
00591 int width, height, x, y;
00592 SDL_Rect rect;
00593 int i;
00594
00595 vp = &is->pictq[is->pictq_rindex];
00596 if (vp->bmp) {
00597
00598 if (is->video_st->codec->sample_aspect_ratio.num == 0)
00599 aspect_ratio = 0;
00600 else
00601 aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio)
00602 * is->video_st->codec->width / is->video_st->codec->height;;
00603 if (aspect_ratio <= 0.0)
00604 aspect_ratio = (float)is->video_st->codec->width /
00605 (float)is->video_st->codec->height;
00606
00607
00608
00609 if (is->subtitle_st)
00610 {
00611 if (is->subpq_size > 0)
00612 {
00613 sp = &is->subpq[is->subpq_rindex];
00614
00615 if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
00616 {
00617 SDL_LockYUVOverlay (vp->bmp);
00618
00619 pict.data[0] = vp->bmp->pixels[0];
00620 pict.data[1] = vp->bmp->pixels[2];
00621 pict.data[2] = vp->bmp->pixels[1];
00622
00623 pict.linesize[0] = vp->bmp->pitches[0];
00624 pict.linesize[1] = vp->bmp->pitches[2];
00625 pict.linesize[2] = vp->bmp->pitches[1];
00626
00627 for (i = 0; i < sp->sub.num_rects; i++)
00628 blend_subrect(&pict, &sp->sub.rects[i]);
00629
00630 SDL_UnlockYUVOverlay (vp->bmp);
00631 }
00632 }
00633 }
00634
00635
00636
00637 height = is->height;
00638 width = ((int)rint(height * aspect_ratio)) & -3;
00639 if (width > is->width) {
00640 width = is->width;
00641 height = ((int)rint(width / aspect_ratio)) & -3;
00642 }
00643 x = (is->width - width) / 2;
00644 y = (is->height - height) / 2;
00645 if (!is->no_background) {
00646
00647
00648 } else {
00649 is->no_background = 0;
00650 }
00651 rect.x = is->xleft + x;
00652 rect.y = is->xleft + y;
00653 rect.w = width;
00654 rect.h = height;
00655 SDL_DisplayYUVOverlay(vp->bmp, &rect);
00656 } else {
00657
00658 }
00659 }
00660
00661 void qtffthread::blend_subrect(AVPicture *dst, const AVSubtitleRect *rect)
00662 {
00663 int wrap, wrap3, width2, skip2;
00664 int y, u, v, a, u1, v1, a1, w, h;
00665 uint8_t *lum, *cb, *cr;
00666 const uint8_t *p;
00667 const uint32_t *pal;
00668
00669 lum = dst->data[0] + rect->y * dst->linesize[0];
00670 cb = dst->data[1] + (rect->y >> 1) * dst->linesize[1];
00671 cr = dst->data[2] + (rect->y >> 1) * dst->linesize[2];
00672
00673 width2 = (rect->w + 1) >> 1;
00674 skip2 = rect->x >> 1;
00675 wrap = dst->linesize[0];
00676 wrap3 = rect->linesize;
00677 p = rect->bitmap;
00678 pal = rect->rgba_palette;
00679
00680 if (rect->y & 1) {
00681 lum += rect->x;
00682 cb += skip2;
00683 cr += skip2;
00684
00685 if (rect->x & 1) {
00686 YUVA_IN(y, u, v, a, p, pal);
00687 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00688 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00689 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00690 cb++;
00691 cr++;
00692 lum++;
00693 p += BPP;
00694 }
00695 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
00696 YUVA_IN(y, u, v, a, p, pal);
00697 u1 = u;
00698 v1 = v;
00699 a1 = a;
00700 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00701
00702 YUVA_IN(y, u, v, a, p + BPP, pal);
00703 u1 += u;
00704 v1 += v;
00705 a1 += a;
00706 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00707 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00708 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00709 cb++;
00710 cr++;
00711 p += 2 * BPP;
00712 lum += 2;
00713 }
00714 if (w) {
00715 YUVA_IN(y, u, v, a, p, pal);
00716 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00717 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00718 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00719 }
00720 p += wrap3 + (wrap3 - rect->w * BPP);
00721 lum += wrap + (wrap - rect->w - rect->x);
00722 cb += dst->linesize[1] - width2 - skip2;
00723 cr += dst->linesize[2] - width2 - skip2;
00724 }
00725 for(h = rect->h - (rect->y & 1); h >= 2; h -= 2) {
00726 lum += rect->x;
00727 cb += skip2;
00728 cr += skip2;
00729
00730 if (rect->x & 1) {
00731 YUVA_IN(y, u, v, a, p, pal);
00732 u1 = u;
00733 v1 = v;
00734 a1 = a;
00735 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00736 p += wrap3;
00737 lum += wrap;
00738 YUVA_IN(y, u, v, a, p, pal);
00739 u1 += u;
00740 v1 += v;
00741 a1 += a;
00742 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00743 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00744 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00745 cb++;
00746 cr++;
00747 p += -wrap3 + BPP;
00748 lum += -wrap + 1;
00749 }
00750 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
00751 YUVA_IN(y, u, v, a, p, pal);
00752 u1 = u;
00753 v1 = v;
00754 a1 = a;
00755 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00756
00757 YUVA_IN(y, u, v, a, p, pal);
00758 u1 += u;
00759 v1 += v;
00760 a1 += a;
00761 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00762 p += wrap3;
00763 lum += wrap;
00764
00765 YUVA_IN(y, u, v, a, p, pal);
00766 u1 += u;
00767 v1 += v;
00768 a1 += a;
00769 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00770
00771 YUVA_IN(y, u, v, a, p, pal);
00772 u1 += u;
00773 v1 += v;
00774 a1 += a;
00775 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00776
00777 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2);
00778 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2);
00779
00780 cb++;
00781 cr++;
00782 p += -wrap3 + 2 * BPP;
00783 lum += -wrap + 2;
00784 }
00785 if (w) {
00786 YUVA_IN(y, u, v, a, p, pal);
00787 u1 = u;
00788 v1 = v;
00789 a1 = a;
00790 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00791 p += wrap3;
00792 lum += wrap;
00793 YUVA_IN(y, u, v, a, p, pal);
00794 u1 += u;
00795 v1 += v;
00796 a1 += a;
00797 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00798 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1);
00799 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1);
00800 cb++;
00801 cr++;
00802 p += -wrap3 + BPP;
00803 lum += -wrap + 1;
00804 }
00805 p += wrap3 + (wrap3 - rect->w * BPP);
00806 lum += wrap + (wrap - rect->w - rect->x);
00807 cb += dst->linesize[1] - width2 - skip2;
00808 cr += dst->linesize[2] - width2 - skip2;
00809 }
00810
00811 if (h) {
00812 lum += rect->x;
00813 cb += skip2;
00814 cr += skip2;
00815
00816 if (rect->x & 1) {
00817 YUVA_IN(y, u, v, a, p, pal);
00818 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00819 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00820 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00821 cb++;
00822 cr++;
00823 lum++;
00824 p += BPP;
00825 }
00826 for(w = rect->w - (rect->x & 1); w >= 2; w -= 2) {
00827 YUVA_IN(y, u, v, a, p, pal);
00828 u1 = u;
00829 v1 = v;
00830 a1 = a;
00831 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00832
00833 YUVA_IN(y, u, v, a, p + BPP, pal);
00834 u1 += u;
00835 v1 += v;
00836 a1 += a;
00837 lum[1] = ALPHA_BLEND(a, lum[1], y, 0);
00838 cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1);
00839 cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1);
00840 cb++;
00841 cr++;
00842 p += 2 * BPP;
00843 lum += 2;
00844 }
00845 if (w) {
00846 YUVA_IN(y, u, v, a, p, pal);
00847 lum[0] = ALPHA_BLEND(a, lum[0], y, 0);
00848 cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0);
00849 cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0);
00850 }
00851 }
00852 }
00853
00854 inline int qtffthread::compute_mod(int a, int b)
00855 {
00856 a = a % b;
00857 if (a >= 0)
00858 return a;
00859 else
00860 return a + b;
00861 }
00862
00863 inline void qtffthread::fill_rectangle(SDL_Surface *myscreen,
00864 int x, int y, int w, int h, int color)
00865 {
00866 SDL_Rect rect;
00867 rect.x = x;
00868 rect.y = y;
00869 rect.w = w;
00870 rect.h = h;
00871 SDL_FillRect(myscreen, &rect, color);
00872 }