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 + -
显示快捷键?