static void bb10display_fillWindowBuffer(BB10Display *d, MSPicture *yuvbuf) { uint8_t *ptr = NULL; screen_get_buffer_property_pv(d->pixmap_buffer, SCREEN_PROPERTY_POINTER, (void **)&ptr); if (ptr) { uint8_t *dest_planes[3]; int dest_strides[3]; MSVideoSize roi = {0}; uint8_t *y = ptr; uint8_t *u = y + (d->vsize.height * d->stride); uint8_t *v = u + (d->vsize.height * d->stride) / 4; dest_planes[0] = y; dest_planes[1] = u; dest_planes[2] = v; dest_strides[0] = d->stride; dest_strides[1] = d->stride / 2; dest_strides[2] = d->stride / 2; roi.width = yuvbuf->w; roi.height = yuvbuf->h; ms_yuv_buf_copy(yuvbuf->planes, yuvbuf->strides, dest_planes, dest_strides, roi); screen_buffer_t buffer; screen_get_window_property_pv(d->window, SCREEN_PROPERTY_RENDER_BUFFERS, (void**) &buffer); MSRect rect; ms_layout_center_rectangle(d->wsize, d->vsize, &rect); int attributes[] = { SCREEN_BLIT_SOURCE_WIDTH, d->vsize.width, SCREEN_BLIT_SOURCE_HEIGHT, d->vsize.height, SCREEN_BLIT_DESTINATION_X, rect.x, SCREEN_BLIT_DESTINATION_Y, rect.y, SCREEN_BLIT_DESTINATION_WIDTH, rect.w, SCREEN_BLIT_DESTINATION_HEIGHT, rect.h, SCREEN_BLIT_END }; screen_blit(d->context, buffer, d->pixmap_buffer, attributes); int dirty_rect[4] = { 0, 0, d->wsize.width, d->wsize.height }; screen_post_window(d->window, buffer, 1, dirty_rect, 0); } }
static void h264_dec_output_cb(VTH264DecCtx *ctx, void *sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef imageBuffer, CMTime presentationTimeStamp, CMTime presentationDuration ) { CGSize vsize; MSPicture pixbuf_desc; mblk_t *pixbuf = NULL; uint8_t *src_planes[4] = { NULL }; int src_strides[4] = { 0 }; size_t i; if(status != noErr || imageBuffer == NULL) { ms_error("VideoToolboxDecoder: fail to decode one frame: error %d", status); ms_filter_notify_no_arg(ctx->f, MS_VIDEO_DECODER_DECODING_ERRORS); ms_filter_lock(ctx->f); if(ctx->enable_avpf) { ms_error("VideoToolboxDecoder: sending PLI"); ms_filter_notify_no_arg(ctx->f, MS_VIDEO_DECODER_SEND_PLI); } ms_filter_unlock(ctx->f); return; } vsize = CVImageBufferGetEncodedSize(imageBuffer); ctx->vsize.width = (int)vsize.width; ctx->vsize.height = (int)vsize.height; pixbuf = ms_yuv_buf_allocator_get(ctx->pixbuf_allocator, &pixbuf_desc, (int)vsize.width, (int)vsize.height); CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly); for(i=0; i<3; i++) { src_planes[i] = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, i); src_strides[i] = (int)CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, i); } ms_yuv_buf_copy(src_planes, src_strides, pixbuf_desc.planes, pixbuf_desc.strides, ctx->vsize); CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly); ms_mutex_lock(&ctx->mutex); ms_queue_put(&ctx->queue, pixbuf); ms_mutex_unlock(&ctx->mutex); }
static void x11video_process(MSFilter *f){ X11Video *obj=(X11Video*)f->data; mblk_t *inm; int update=0; MSPicture lsrc={0}; MSPicture src={0}; MSRect mainrect,localrect; bool_t precious=FALSE; bool_t local_precious=FALSE; XWindowAttributes wa; MSTickerLateEvent late_info; ms_filter_lock(f); if ((obj->window_id == 0) || (x11_error == TRUE)) goto end; XGetWindowAttributes(obj->display,obj->window_id,&wa); if (x11_error == TRUE) { ms_error("Could not get window attributes for window %lu", obj->window_id); goto end; } if (wa.width!=obj->wsize.width || wa.height!=obj->wsize.height){ ms_warning("Resized to %ix%i", wa.width,wa.height); obj->wsize.width=wa.width; obj->wsize.height=wa.height; XClearWindow(obj->display,obj->window_id); } ms_ticker_get_last_late_tick(f->ticker, &late_info); if(late_info.current_late_ms > 100) { ms_warning("Dropping frames because we're late"); goto end; } if (!obj->show) { goto end; } if (!obj->ready){ goto end; } if (f->inputs[0]!=NULL && (inm=ms_queue_peek_last(f->inputs[0]))!=0) { if (ms_yuv_buf_init_from_mblk(&src,inm)==0){ MSVideoSize newsize; newsize.width=src.w; newsize.height=src.h; precious=mblk_get_precious_flag(inm); if (!ms_video_size_equal(newsize,obj->vsize) ) { ms_message("received size is %ix%i",newsize.width,newsize.height); obj->vsize=newsize; if (obj->autofit){ MSVideoSize new_window_size; static const MSVideoSize min_size=MS_VIDEO_SIZE_QVGA; /*don't resize less than QVGA, it is too small*/ if (min_size.width*min_size.height>newsize.width*newsize.height){ new_window_size.width=newsize.width*2; new_window_size.height=newsize.height*2; }else new_window_size=newsize; obj->wsize=new_window_size; ms_message("autofit: new window size should be %ix%i",new_window_size.width,new_window_size.height); XResizeWindow(obj->display,obj->window_id,new_window_size.width,new_window_size.height); XSync(obj->display,FALSE); } x11video_unprepare(f); x11video_prepare(f); if (!obj->ready) goto end; } } update=1; } /*process last video message for local preview*/ if (obj->corner!=-1 && f->inputs[1]!=NULL && (inm=ms_queue_peek_last(f->inputs[1]))!=0) { if (ms_yuv_buf_init_from_mblk(&lsrc,inm)==0){ obj->lsize.width=lsrc.w; obj->lsize.height=lsrc.h; local_precious=mblk_get_precious_flag(inm); update=1; } } ms_layout_compute(obj->vsize, obj->vsize,obj->lsize,obj->corner,obj->scale_factor,&mainrect,&localrect); if (lsrc.w!=0 && obj->corner!=-1){ /* first reduce the local preview image into a temporary image*/ if (obj->local_msg==NULL){ obj->local_msg=ms_yuv_buf_alloc(&obj->local_pic,localrect.w,localrect.h); } if (obj->sws2==NULL){ obj->sws2=ms_scaler_create_context(lsrc.w,lsrc.h,MS_YUV420P,localrect.w,localrect.h,MS_YUV420P, MS_SCALER_METHOD_BILINEAR); } ms_scaler_process(obj->sws2,lsrc.planes,lsrc.strides,obj->local_pic.planes,obj->local_pic.strides); if (!local_precious) ms_yuv_buf_mirror(&obj->local_pic); } if (update && src.w!=0){ ms_yuv_buf_copy(src.planes,src.strides,obj->fbuf.planes,obj->fbuf.strides,obj->vsize); if (obj->mirror && !precious) ms_yuv_buf_mirror(&obj->fbuf); } /*copy resized local view into a corner:*/ if (update && obj->local_msg!=NULL && obj->corner!=-1){ MSPicture corner=obj->fbuf; MSVideoSize roi; roi.width=obj->local_pic.w; roi.height=obj->local_pic.h; corner.w=obj->local_pic.w; corner.h=obj->local_pic.h; corner.planes[0]+=localrect.x+(localrect.y*corner.strides[0]); corner.planes[1]+=(localrect.x/2)+((localrect.y/2)*corner.strides[1]); corner.planes[2]+=(localrect.x/2)+((localrect.y/2)*corner.strides[2]); corner.planes[3]=0; ms_yuv_buf_copy(obj->local_pic.planes,obj->local_pic.strides, corner.planes,corner.strides,roi); } if (update){ MSRect rect; ms_layout_center_rectangle(obj->wsize,obj->vsize,&rect); //ms_message("XvShmPutImage() %ix%i --> %ix%i",obj->fbuf.w,obj->fbuf.h,obj->wsize.width,obj->wsize.height); XvShmPutImage(obj->display,obj->port,obj->window_id,obj->gc, obj->xv_image, 0,0,obj->fbuf.w,obj->fbuf.h, rect.x,rect.y,rect.w,rect.h,TRUE); XSync(obj->display,FALSE); } end: ms_filter_unlock(f); if (f->inputs[0]!=NULL) ms_queue_flush(f->inputs[0]); if (f->inputs[1]!=NULL) ms_queue_flush(f->inputs[1]); }
static void h264_enc_process(MSFilter *f) { VTH264EncCtx *ctx = (VTH264EncCtx *)f->data; mblk_t *frame; OSStatus err; CMTime p_time = CMTimeMake(f->ticker->time, 1000); if(!ctx->is_configured) { ms_queue_flush(f->inputs[0]); return; } #if 0 && TARGET_OS_IPHONE CVPixelBufferPoolRef pixbuf_pool = VTCompressionSessionGetPixelBufferPool(ctx->session); if(pixbuf_pool == NULL) { ms_error("VideoToolbox: fails to get the pixel buffer pool"); return; } #endif while((frame = ms_queue_get(f->inputs[0]))) { YuvBuf src_yuv_frame, dst_yuv_frame = {0}; CVPixelBufferRef pixbuf; CFMutableDictionaryRef enc_param = NULL; int i, pixbuf_fmt = kCVPixelFormatType_420YpCbCr8Planar; CFNumberRef value; CFMutableDictionaryRef pixbuf_attr; ms_yuv_buf_init_from_mblk(&src_yuv_frame, frame); #if 0 && TARGET_OS_IPHONE CVPixelBufferPoolCreatePixelBuffer(NULL, pixbuf_pool, &pixbuf); #else pixbuf_attr = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); value = CFNumberCreate(NULL, kCFNumberIntType, &pixbuf_fmt); CFDictionarySetValue(pixbuf_attr, kCVPixelBufferPixelFormatTypeKey, value); CVPixelBufferCreate(NULL, ctx->conf.vsize.width, ctx->conf.vsize.height, kCVPixelFormatType_420YpCbCr8Planar, pixbuf_attr, &pixbuf); CFRelease(pixbuf_attr); #endif CVPixelBufferLockBaseAddress(pixbuf, 0); dst_yuv_frame.w = (int)CVPixelBufferGetWidth(pixbuf); dst_yuv_frame.h = (int)CVPixelBufferGetHeight(pixbuf); for(i=0; i<3; i++) { dst_yuv_frame.planes[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i); dst_yuv_frame.strides[i] = (int)CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i); } ms_yuv_buf_copy(src_yuv_frame.planes, src_yuv_frame.strides, dst_yuv_frame.planes, dst_yuv_frame.strides, (MSVideoSize){dst_yuv_frame.w, dst_yuv_frame.h}); CVPixelBufferUnlockBaseAddress(pixbuf, 0); freemsg(frame); ms_filter_lock(f); if(ctx->fps_changed || ctx->bitrate_changed || ctx->vfu_requested) { CFNumberRef value; enc_param = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); if(ctx->fps_changed) { value = CFNumberCreate(NULL, kCFNumberFloatType, &ctx->conf.fps); CFDictionaryAddValue(enc_param, kVTCompressionPropertyKey_ExpectedFrameRate, value); ctx->fps_changed = FALSE; } if(ctx->bitrate_changed) { value = CFNumberCreate(NULL, kCFNumberIntType, &ctx->conf.required_bitrate); CFDictionaryAddValue(enc_param, kVTCompressionPropertyKey_AverageBitRate, value); ctx->bitrate_changed = FALSE; } if(ctx->vfu_requested) { int force_keyframe = 1; value = CFNumberCreate(NULL, kCFNumberIntType, &force_keyframe); CFDictionaryAddValue(enc_param, kVTEncodeFrameOptionKey_ForceKeyFrame, value); ctx->vfu_requested = FALSE; } } ms_filter_unlock(f); if(!ctx->enable_avpf) { if(ctx->first_frame) { ms_video_starter_first_frame(&ctx->starter, f->ticker->time); } if(ms_video_starter_need_i_frame(&ctx->starter, f->ticker->time)) { if(enc_param == NULL) enc_param = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); if(CFDictionaryGetValue(enc_param, kVTEncodeFrameOptionKey_ForceKeyFrame) == NULL) { int force_keyframe = 1; CFNumberRef value = CFNumberCreate(NULL, kCFNumberIntType, &force_keyframe); CFDictionaryAddValue(enc_param, kVTEncodeFrameOptionKey_ForceKeyFrame, value); } } } if((err = VTCompressionSessionEncodeFrame(ctx->session, pixbuf, p_time, kCMTimeInvalid, enc_param, NULL, NULL)) != noErr) { ms_error("VideoToolbox: could not pass a pixbuf to the encoder: error code %d", err); } CFRelease(pixbuf); ctx->first_frame = FALSE; if(enc_param) CFRelease(enc_param); } ms_mutex_lock(&ctx->mutex); while ((frame = ms_queue_get(&ctx->queue))) { ms_mutex_unlock(&ctx->mutex); ms_queue_put(f->outputs[0], frame); ms_mutex_lock(&ctx->mutex); } ms_mutex_unlock(&ctx->mutex); }