xine_plugin.c
来自「linux下的MPEG1」· C语言 代码 · 共 927 行 · 第 1/3 页
C
927 行
deinterlaced_frame->base[0], yuy2_frame->base[0], (this->recent_frame[0])?this->recent_frame[0]->base[0]:yuy2_frame->base[0], (this->recent_frame[1])?this->recent_frame[1]->base[0]:yuy2_frame->base[0], bottom_field, second_field, frame->width, frame->height, yuy2_frame->pitches[0], deinterlaced_frame->pitches[0]); } else { deinterlaced_frame->bad_frame = !tvtime_build_deinterlaced_frame(this->tvtime, deinterlaced_frame->base[0], yuy2_frame->base[0], (this->recent_frame[0])?this->recent_frame[0]->base[0]:yuy2_frame->base[0], (this->recent_frame[1])?this->recent_frame[1]->base[0]:yuy2_frame->base[0], bottom_field, second_field, frame->width/2, frame->height, yuy2_frame->pitches[0], deinterlaced_frame->pitches[0]); deinterlaced_frame->bad_frame += !tvtime_build_deinterlaced_frame(this->tvtime, deinterlaced_frame->base[1], yuy2_frame->base[1], (this->recent_frame[0])?this->recent_frame[0]->base[1]:yuy2_frame->base[1], (this->recent_frame[1])?this->recent_frame[1]->base[1]:yuy2_frame->base[1], bottom_field, second_field, frame->width/4, frame->height/2, yuy2_frame->pitches[1], deinterlaced_frame->pitches[1]); deinterlaced_frame->bad_frame += !tvtime_build_deinterlaced_frame(this->tvtime, deinterlaced_frame->base[2], yuy2_frame->base[2], (this->recent_frame[0])?this->recent_frame[0]->base[2]:yuy2_frame->base[2], (this->recent_frame[1])?this->recent_frame[1]->base[2]:yuy2_frame->base[2], bottom_field, second_field, frame->width/4, frame->height/2, yuy2_frame->pitches[2], deinterlaced_frame->pitches[2]); } } } pthread_mutex_unlock (&this->lock); if( force24fps ) { if( !deinterlaced_frame->bad_frame ) { this->framecounter++; if( pts && this->framecounter > FRAMES_TO_SYNC ) { deinterlaced_frame->pts = pts; this->framecounter = 0; } else deinterlaced_frame->pts = 0; deinterlaced_frame->duration = FPS_24_DURATION; if( this->chroma_filter && !this->cheap_mode ) apply_chroma_filter( deinterlaced_frame->base[0], deinterlaced_frame->pitches[0], frame->width, frame->height / scaler ); skip = deinterlaced_frame->draw(deinterlaced_frame, stream); } else { skip = 0; } } else { deinterlaced_frame->pts = pts; deinterlaced_frame->duration = duration; if( this->chroma_filter && !this->cheap_mode && !deinterlaced_frame->bad_frame ) apply_chroma_filter( deinterlaced_frame->base[0], deinterlaced_frame->pitches[0], frame->width, frame->height / scaler ); skip = deinterlaced_frame->draw(deinterlaced_frame, stream); } /* _x_post_frame_copy_up(frame, deinterlaced_frame); */ deinterlaced_frame->free(deinterlaced_frame); pthread_mutex_lock (&this->lock); return skip;}static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream){ post_video_port_t *port = (post_video_port_t *)frame->port; post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post; vo_frame_t *orig_frame; vo_frame_t *yuy2_frame; int i, skip = 0, progressive = 0; int fields[2]; int framerate_mode; orig_frame = frame; _x_post_frame_copy_down(frame, frame->next); frame = frame->next; /* update tvtime context and method */ pthread_mutex_lock (&this->lock); if( this->tvtime_changed ) { tvtime_reset_context(this->tvtime); if( this->cur_method ) this->tvtime->curmethod = get_deinterlace_method( this->cur_method-1 ); else this->tvtime->curmethod = NULL; port->original_port->set_property(port->original_port, XINE_PARAM_VO_DEINTERLACE, !this->cur_method); this->tvtime_changed = 0; } if( this->tvtime_last_filmmode != this->tvtime->filmmode ) { xine_event_t event; event.type = XINE_EVENT_POST_TVTIME_FILMMODE_CHANGE; event.stream = stream; event.data = (void *)&this->tvtime->filmmode; event.data_length = sizeof(this->tvtime->filmmode); xine_event_send(stream, &event); this->tvtime_last_filmmode = this->tvtime->filmmode; } pthread_mutex_unlock (&this->lock); lprintf("frame flags pf: %d rff: %d tff: %d duration: %d\n", frame->progressive_frame, frame->repeat_first_field, frame->top_field_first, frame->duration); /* detect special rff patterns */ this->rff_pattern = this->rff_pattern << 1; this->rff_pattern |= !!frame->repeat_first_field; if( ((this->rff_pattern & 0xff) == 0xaa || (this->rff_pattern & 0xff) == 0x55) ) { /* * special case for ntsc 3:2 pulldown (called flags or soft pulldown). * we know all frames are indeed progressive. */ progressive = 1; } /* using frame->progressive_frame may help displaying still menus. * however, it is known that some rare material set it wrong. * * we also assume that repeat_first_field is progressive (it doesn't * make much sense to display interlaced fields out of order) */ if( this->use_progressive_frame_flag && (frame->repeat_first_field || frame->progressive_frame) ) { progressive = 1; } if( !frame->bad_frame && (frame->flags & VO_INTERLACED_FLAG) && this->tvtime->curmethod ) { frame->flags &= ~VO_INTERLACED_FLAG; /* convert to YUY2 if needed */ if( frame->format == XINE_IMGFMT_YV12 && !this->cheap_mode ) { yuy2_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, XINE_IMGFMT_YUY2, frame->flags | VO_BOTH_FIELDS); _x_post_frame_copy_down(frame, yuy2_frame); /* the logic for deciding upsampling to use comes from: * http://www.hometheaterhifi.com/volume_8_2/dvd-benchmark-special-report-chroma-bug-4-2001.html */ yv12_to_yuy2(frame->base[0], frame->pitches[0], frame->base[1], frame->pitches[1], frame->base[2], frame->pitches[2], yuy2_frame->base[0], yuy2_frame->pitches[0], frame->width, frame->height, frame->progressive_frame || progressive ); } else { yuy2_frame = frame; yuy2_frame->lock(yuy2_frame); } pthread_mutex_lock (&this->lock); /* check if frame format changed */ for(i = 0; i < NUM_RECENT_FRAMES; i++ ) { if( this->recent_frame[i] && (this->recent_frame[i]->width != frame->width || this->recent_frame[i]->height != frame->height || this->recent_frame[i]->format != yuy2_frame->format ) ) { this->recent_frame[i]->free(this->recent_frame[i]); this->recent_frame[i] = NULL; } } if( !this->cheap_mode ) { framerate_mode = this->framerate_mode; this->tvtime->pulldown_alg = this->pulldown; } else { framerate_mode = FRAMERATE_HALF_TFF; this->tvtime->pulldown_alg = PULLDOWN_NONE; } if( framerate_mode == FRAMERATE_FULL ) { int top_field_first = frame->top_field_first; /* if i understood mpeg2 specs correctly, top_field_first * shall be zero for field pictures and the output order * is the same that the fields are decoded. * frame->flags allow us to find the first decoded field. * * note: frame->field() is called later to switch decoded * field but frame->flags do not change. */ if ( (frame->flags & VO_BOTH_FIELDS) != VO_BOTH_FIELDS ) { top_field_first = (frame->flags & VO_TOP_FIELD) ? 1 : 0; } if ( top_field_first ) { fields[0] = 0; fields[1] = 1; } else { fields[0] = 1; fields[1] = 0; } } else if ( framerate_mode == FRAMERATE_HALF_TFF ) { fields[0] = 0; } else if ( framerate_mode == FRAMERATE_HALF_BFF ) { fields[0] = 1; } if( progressive ) { /* If the previous field was interlaced and this one is progressive * we need to run a deinterlace on the first field of this frame * in order to let output for the previous frames last field be * generated. This is only necessary for the deinterlacers that * delay output by one field. This is signaled by the delaysfield * flag in the deinterlace method structure. The previous frames * duration is used in the calculation because the generated frame * represents the second half of the previous frame. */ if (this->recent_frame[0] && !this->recent_frame[0]->progressive_frame && this->tvtime->curmethod->delaysfield) { skip = deinterlace_build_output_field( this, port, stream, frame, yuy2_frame, fields[0], 0, 0, (framerate_mode == FRAMERATE_FULL) ? this->recent_frame[0]->duration/2 : this->recent_frame[0]->duration, 0); } pthread_mutex_unlock (&this->lock); skip = yuy2_frame->draw(yuy2_frame, stream); pthread_mutex_lock (&this->lock); _x_post_frame_copy_up(frame, yuy2_frame); } else { /* If the previous field was progressive and we are using a * filter that delays it's output by one field then we need * to skip the first field's output. Otherwise the effective * display duration of the previous frame will be extended * by 1/2 of this frames duration when output is generated * using the last field of the progressive frame. */ /* Build the output from the first field. */ if ( !(this->recent_frame[0] && this->recent_frame[0]->progressive_frame && this->tvtime->curmethod->delaysfield) ) { skip = deinterlace_build_output_field( this, port, stream, frame, yuy2_frame, fields[0], 0, frame->pts, (framerate_mode == FRAMERATE_FULL) ? frame->duration/2 : frame->duration, 0); } if( framerate_mode == FRAMERATE_FULL ) { /* Build the output from the second field. */ skip = deinterlace_build_output_field( this, port, stream, frame, yuy2_frame, fields[1], 1, 0, frame->duration/2, skip); } } /* don't drop frames when pulldown mode is enabled. otherwise * pulldown detection fails (yo-yo effect has also been seen) */ if( this->pulldown ) skip = 0; /* store back progressive flag for frame history */ yuy2_frame->progressive_frame = progressive; /* keep track of recent frames */ i = NUM_RECENT_FRAMES-1; if( this->recent_frame[i] ) this->recent_frame[i]->free(this->recent_frame[i]); for( ; i ; i-- ) this->recent_frame[i] = this->recent_frame[i-1]; if (port->stream) this->recent_frame[0] = yuy2_frame; else { /* do not keep this frame when no stream is connected to us, * otherwise, this frame might never get freed */ yuy2_frame->free(yuy2_frame); this->recent_frame[0] = NULL; } pthread_mutex_unlock (&this->lock); } else { skip = frame->draw(frame, stream); } _x_post_frame_copy_up(orig_frame, frame); return skip;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?