⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idirectfbvideoprovider_openquicktime.c

📁 videoprovider and imageprovider for directfb
💻 C
📖 第 1 页 / 共 3 页
字号:
WriteYUVFrame( IDirectFBVideoProvider_OpenQuicktime_data *data ){     __u16                 *dst;     unsigned int           pitch;     CoreSurface           *surface;     IDirectFBSurface_data *dst_data;     __u8                  *src_y, *src_u, *src_v;     __u8                  *dst_y, *dst_u, *dst_v;     int                    x, y, off_x, off_y;     dst_data = (IDirectFBSurface_data*) data->destination->priv;     surface  = dst_data->surface;     dfb_surface_soft_lock( surface, DSLF_WRITE, (void**)&dst, &pitch, 0 );     src_y  = data->yuv.lines[0];     src_u  = data->yuv.lines[1];     src_v  = data->yuv.lines[2];     off_x  = data->dest_clip.x - data->dest_rect.x;     off_y  = data->dest_clip.y - data->dest_rect.y;     src_y +=  off_y * data->video.width + off_x;     src_u += (off_y / 2) * (data->video.width / 2) + off_x / 2;     src_v += (off_y / 2) * (data->video.width / 2) + off_x / 2;     /* this code might not work with offsets not being a multiple of 2 */     switch (surface->format) {          case DSPF_I420:          case DSPF_YV12:               dst_y  = (__u8*) dst;               dst_y += data->dest_clip.y * pitch + data->dest_clip.x;               if (surface->format == DSPF_I420) {                    dst_u = (__u8*) dst + pitch * data->video.height;                    dst_v = dst_u + pitch/2 * data->video.height / 2;                    dst_u += data->dest_clip.y/2 * pitch/2 + data->dest_clip.x/2;                    dst_v += data->dest_clip.y/2 * pitch/2 + data->dest_clip.x/2;               }               else {                    dst_v = (__u8*) dst + pitch * data->video.height;                    dst_u = dst_v + pitch/2 * data->video.height / 2;                    dst_u += data->dest_clip.y/2 * pitch/2 + data->dest_clip.x/2;                    dst_v += data->dest_clip.y/2 * pitch/2 + data->dest_clip.x/2;               }               for (y=0; y<data->dest_clip.h; y++) {                    dfb_memcpy( dst_y, src_y, data->dest_clip.w );                    src_y += data->video.width;                    dst_y += pitch;                    if (y & 1) {                         src_u += data->video.width/2;                         src_v += data->video.width/2;                         dst_u += pitch/2;                         dst_v += pitch/2;                    }                    else {                         dfb_memcpy( dst_u, src_u, data->dest_clip.w/2 );                         dfb_memcpy( dst_v, src_v, data->dest_clip.w/2 );                    }               }               break;          case DSPF_YUY2:               dst += data->dest_clip.y * pitch + data->dest_clip.x;               for (y=0; y<data->dest_clip.h; y++) {                    for (x=0; x<data->dest_clip.w; x++) {                         if (x & 1)                              dst[x] = (src_v[x/2] << 8) | src_y[x];                         else                              dst[x] = (src_u[x/2] << 8) | src_y[x];                    }                    src_y += data->video.width;                    if (y & 1) {                         src_u += data->video.width/2;                         src_v += data->video.width/2;                    }                    dst += pitch/2;               }               break;          case DSPF_UYVY:               dst += data->dest_clip.y * pitch + data->dest_clip.x;               for (y=0; y<data->dest_clip.h; y++) {                    for (x=0; x<data->dest_clip.w; x++) {                         if (x & 1)                              dst[x] = (src_y[x] << 8) | src_v[x/2];                         else                              dst[x] = (src_y[x] << 8) | src_u[x/2];                    }                    src_y += data->video.width;                    if (y & 1) {                         src_u += data->video.width/2;                         src_v += data->video.width/2;                    }                    dst += pitch/2;               }               break;          default:               break;     }     dfb_surface_unlock( dst_data->surface, 0 );}static void*VideoThread( void *ctx ){     IDirectFBVideoProvider_OpenQuicktime_data *data =          (IDirectFBVideoProvider_OpenQuicktime_data*) ctx;     struct timeval start, after;     long   frame_delay;     long   delay = -1;     double rate;     int    drop = 0;     long   frame, start_frame = 0;     long   frames;     rate = data->video.rate / 1000.0;     frame_delay = (long) (1000 / data->video.rate);     frames = data->video.length;     if (frames == 1)          frames = -1;     data->video.seeked = 1;     while (data->video.playing) {          pthread_mutex_lock( &data->video.lock );          if (!data->video.playing) {               pthread_mutex_unlock( &data->video.lock );               break;          }          if (data->video.seeked) {               drop = 0;               gettimeofday(&start, 0);               start_frame = quicktime_video_position( data->file, 0 );               data->video.seeked = 0;          }          if (drop) {               while (drop--)                    quicktime_decode_video( data->file, BC_NONE, NULL, 0 );               drop = 0;          }          else {               int ret;               if (data->video.yuv)                    ret = quicktime_decode_video( data->file, BC_YUV420P,                                                  data->yuv.lines, 0 );               else                    ret = quicktime_decode_video( data->file, BC_RGB888,                                                  data->rgb.lines, 0 );               if (ret) {                    pthread_mutex_unlock( &data->video.lock );                    break;               }               if (data->video.yuv)                    WriteYUVFrame( data );               else                    WriteRGBFrame( data );               if (data->callback)                    data->callback (data->ctx);          }          frame = quicktime_video_position( data->file, 0 );          gettimeofday (&after, 0);          delay = (after.tv_sec - start.tv_sec) * 1000 +                  (after.tv_usec - start.tv_usec) / 1000;          {               long cframe = (long) (delay * rate) + start_frame;               if ( frame < cframe ) {                    drop = cframe - frame;                    pthread_mutex_unlock( &data->video.lock );                    continue;               }               else if ( frame == cframe )                    delay = ((long) ((frame - start_frame + 1) / rate)) - delay;               else                    delay = frame_delay;          }          after.tv_sec = 0;          after.tv_usec = delay * 1000;          pthread_mutex_unlock( &data->video.lock );          select( 0, 0, 0, 0, &after );          /* jump to start if arrived at last frame  */          if (frame == frames) {               pthread_mutex_lock( &data->video.lock );               pthread_mutex_lock( &data->audio.lock );               quicktime_seek_start( data->file );               data->video.seeked = 1;               data->audio.seeked = 1;               pthread_mutex_unlock( &data->audio.lock );               pthread_mutex_unlock( &data->video.lock );          }     }     return NULL;}static void*AudioThread( void *ctx ){     IDirectFBVideoProvider_OpenQuicktime_data *data =          (IDirectFBVideoProvider_OpenQuicktime_data*) ctx;     __s16 buffer[data->audio.samples_per_block * data->audio.channels];     __s16 left[data->audio.samples_per_block];     __s16 right[data->audio.samples_per_block];     /* calculate audio position */     long audio_pos = (long) ((double)quicktime_video_position (data->file, 0) *                              (double)data->audio.rate /                              (double)data->video.rate);     /* seek audio */     quicktime_set_audio_position( data->file, audio_pos, 0 );     data->audio.seeked = 1;     while (data->audio.playing) {          pthread_mutex_lock( &data->audio.lock );          if (!data->audio.playing) {               pthread_mutex_unlock( &data->audio.lock );               break;          }          if (data->audio.seeked) {               /* flush buffered audio data */               ioctl( data->audio.fd, SNDCTL_DSP_RESET, 0 );               data->audio.seeked = 0;          }          if (data->audio.channels == 1) {               long pos = quicktime_audio_position( data->file, 0 );               /* mono */               if ((pos < 0) ||                   (pos + data->audio.samples_per_block) >= data->audio.length ||                   quicktime_decode_audio( data->file, buffer, NULL,                                           data->audio.samples_per_block, 0 ))                    memset( buffer, 0, data->audio.block_size );               write( data->audio.fd, buffer, data->audio.block_size );          }          else {               long pos = quicktime_audio_position( data->file, 0 );               /* stereo */               if ((pos < 0) ||                   (pos + data->audio.samples_per_block) >= data->audio.length ||                   quicktime_decode_audio( data->file, left, NULL,                                           data->audio.samples_per_block, 0 ))                    memset( buffer, 0, data->audio.block_size );               else {                    int i;                    quicktime_set_audio_position( data->file, pos, 0 );                    quicktime_decode_audio( data->file, right, NULL,                                            data->audio.samples_per_block, 1 );                    /* produce interleaved buffer */                    for (i=0; i<data->audio.samples_per_block; i++) {                         buffer[i*2+0] = left[i];                         buffer[i*2+1] = right[i];                    }               }               write( data->audio.fd, buffer, data->audio.block_size );          }          pthread_mutex_unlock( &data->audio.lock );     }     /* tell sound driver that we stopped playback */     ioctl( data->audio.fd, SNDCTL_DSP_POST, 0 );     return NULL;}static DFBResultIDirectFBVideoProvider_OpenQuicktime_PlayTo( IDirectFBVideoProvider *thiz,                                        IDirectFBSurface       *destination,                                        DFBRectangle           *dstrect,                                        DVFrameCallback         callback,                                        void                   *ctx ){     int                    yuv_mode = 0;     DFBRectangle           rect, dest_rect, dest_clip;     IDirectFBSurface_data *dst_data;     INTERFACE_GET_DATA (IDirectFBVideoProvider_OpenQuicktime)     if (!destination)          return DFB_INVARG;     dst_data = (IDirectFBSurface_data*)destination->priv;     if (!dst_data)          return DFB_DEAD;     /* check if destination format is supported */     switch (dst_data->surface->format) {          case DSPF_I420:          case DSPF_YV12:          case DSPF_YUY2:          case DSPF_UYVY:               if (!data->yuv.supported)                    return DFB_UNSUPPORTED;               yuv_mode = 1;               break;          case DSPF_RGB332:          case DSPF_RGB15:          case DSPF_RGB16:          case DSPF_RGB24:          case DSPF_RGB32:          case DSPF_ARGB:               if (data->rgb.supported)                    break;          default:               return DFB_UNSUPPORTED;     }     /* build the destination rectangle */     if (dstrect) {          if (dstrect->w < 1  ||  dstrect->h < 1)               return DFB_INVARG;          rect = *dstrect;          rect.x += dst_data->area.wanted.x;          rect.y += dst_data->area.wanted.y;     }     else          rect = dst_data->area.wanted;     /* check destination rect and save it */     if (rect.w != data->video.width || rect.h != data->video.height)          return DFB_UNSUPPORTED;     dest_rect = rect;     /* build the clip rectangle */     if (!dfb_rectangle_intersect( &rect, &dst_data->area.current ))          return DFB_INVARG;     dest_clip = rect;     pthread_mutex_lock( &data->video.lock );     /* release previous destination surface */     if (data->destination) {          data->destination->Release( data->destination );          data->destination = NULL;     /* FIXME: remove listener */     }     /* reference destination surface */     destination->AddRef( destination );     data->destination = destination;   /* FIXME: install listener */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -