void VideoStreamPlaybackTheora::video_write(void) { th_ycbcr_buffer yuv; th_decode_ycbcr_out(td, yuv); int pitch = 4; frame_data.resize(size.x * size.y * pitch); { PoolVector<uint8_t>::Write w = frame_data.write(); char *dst = (char *)w.ptr(); //uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y/2); if (px_fmt == TH_PF_444) { yuv444_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0); } else if (px_fmt == TH_PF_422) { yuv422_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0); } else if (px_fmt == TH_PF_420) { yuv420_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[2].data, (uint8_t *)yuv[1].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0); }; format = Image::FORMAT_RGBA8; } Ref<Image> img = memnew(Image(size.x, size.y, 0, Image::FORMAT_RGBA8, frame_data)); //zero copy image creation texture->set_data(img); //zero copy send to visual server frames_pending = 1; }
int ff_h264_decode(unsigned char* pInNaluBuf, int inLen, unsigned char *pOutRgbaBuf, int *pw, int *ph) { if(!pCodecCtx) return -1; AVPacket avpkt; av_init_packet(&avpkt); avpkt.size = inLen; avpkt.data = pInNaluBuf; int ret, got_frame; ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_frame, &avpkt); if (ret < 0) { return -1; } if (got_frame) { *pw = pCodecCtx->width; *ph = pCodecCtx->height; //将yuv格式数据转换为目标格式抛出 //ret = AVFrame2Rgba(pFrame, pOutRgbaBuf, pw, ph); yuv420_2_rgb8888(pOutRgbaBuf, pFrame->data[0], pFrame->data[1], pFrame->data[2], pCodecCtx->width, pCodecCtx->height, pCodecCtx->width, pCodecCtx->width/2, pCodecCtx->width*4,yuv2rgb565_table, 0); } av_free_packet(&avpkt); return ret; }
void watts (unsigned char* dst_ptr, unsigned char*y_ptr, unsigned char*u_ptr, unsigned char*v_ptr, int width, int height, int y_span, int uv_span, int dst_span) { yuv420_2_rgb8888 (dst_ptr, (const uint8_t *)y_ptr, (const uint8_t *)u_ptr, (const uint8_t *)v_ptr, width, height, y_span, uv_span, dst_span, yuv2rgb565_table, 0); }
void VideoStreamPlaybackWebm::update(float p_delta) { if ((!playing || paused) || !video) return; time += p_delta; if (time < video_pos) { return; } bool audio_buffer_full = false; if (samples_offset > -1) { //Mix remaining samples const int to_read = num_decoded_samples - samples_offset; const int mixed = mix_callback(mix_udata, pcm + samples_offset * webm->getChannels(), to_read); if (mixed != to_read) { samples_offset += mixed; audio_buffer_full = true; } else { samples_offset = -1; } } const bool hasAudio = (audio && mix_callback); while ((hasAudio && !audio_buffer_full && !has_enough_video_frames()) || (!hasAudio && video_frames_pos == 0)) { if (hasAudio && !audio_buffer_full && audio_frame->isValid() && audio->getPCMF(*audio_frame, pcm, num_decoded_samples) && num_decoded_samples > 0) { const int mixed = mix_callback(mix_udata, pcm, num_decoded_samples); if (mixed != num_decoded_samples) { samples_offset = mixed; audio_buffer_full = true; } } WebMFrame *video_frame; if (video_frames_pos >= video_frames_capacity) { WebMFrame **video_frames_new = (WebMFrame **)memrealloc(video_frames, ++video_frames_capacity * sizeof(void *)); ERR_FAIL_COND(!video_frames_new); //Out of memory (video_frames = video_frames_new)[video_frames_capacity - 1] = memnew(WebMFrame); } video_frame = video_frames[video_frames_pos]; if (!webm->readFrame(video_frame, audio_frame)) //This will invalidate frames break; //Can't demux, EOS? if (video_frame->isValid()) ++video_frames_pos; }; bool video_frame_done = false; while (video_frames_pos > 0 && !video_frame_done) { WebMFrame *video_frame = video_frames[0]; // It seems VPXDecoder::decode has to be executed even though we might skip this frame if (video->decode(*video_frame)) { VPXDecoder::IMAGE_ERROR err; VPXDecoder::Image image; if (should_process(*video_frame)) { if ((err = video->getImage(image)) != VPXDecoder::NO_FRAME) { if (err == VPXDecoder::NO_ERROR && image.w == webm->getWidth() && image.h == webm->getHeight()) { PoolVector<uint8_t>::Write w = frame_data.write(); bool converted = false; if (image.chromaShiftW == 1 && image.chromaShiftH == 1) { yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0); // libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) { yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0); // libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) { yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0); // libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) { // libyuv::I411ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); // converted = true; } if (converted) { Ref<Image> img = memnew(Image(image.w, image.h, 0, Image::FORMAT_RGBA8, frame_data)); texture->set_data(img); //Zero copy send to visual server video_frame_done = true; } } } } } video_pos = video_frame->time; memmove(video_frames, video_frames + 1, (--video_frames_pos) * sizeof(void *)); video_frames[video_frames_pos] = video_frame; } if (video_frames_pos == 0 && webm->isEOS()) stop(); }
void VideoStreamTheora::video_write(void){ th_ycbcr_buffer yuv; int y_offset, uv_offset; th_decode_ycbcr_out(td,yuv); y_offset=(ti.pic_x&~1)+yuv[0].stride*(ti.pic_y&~1); /* { int pixels = size.x * size.y; frame_data.resize(pixels * 4); DVector<uint8_t>::Write w = frame_data.write(); char* dst = (char*)w.ptr(); int p = 0; for (int i=0; i<size.y; i++) { char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; char *out = dst + (int)size.x * 4 * i; for (int j=0;j<size.x;j++) { dst[p++] = in_y[j]; dst[p++] = in_y[j]; dst[p++] = in_y[j]; dst[p++] = 255; }; } format = Image::FORMAT_RGBA; } // */ //* int pitch = 4; frame_data.resize(size.x * size.y * pitch); DVector<uint8_t>::Write w = frame_data.write(); char* dst = (char*)w.ptr(); uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y/2); if (px_fmt == TH_PF_444) { yuv444_2_rgb8888((uint8_t*)dst, (uint8_t*)yuv[0].data, (uint8_t*)yuv[1].data, (uint8_t*)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x<<2, 0); } else if (px_fmt == TH_PF_422) { yuv422_2_rgb8888((uint8_t*)dst, (uint8_t*)yuv[0].data, (uint8_t*)yuv[1].data, (uint8_t*)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x<<2, 0); } else if (px_fmt == TH_PF_420) { yuv420_2_rgb8888((uint8_t*)dst, (uint8_t*)yuv[0].data, (uint8_t*)yuv[2].data, (uint8_t*)yuv[1].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x<<2, 0); }; format = Image::FORMAT_RGBA; /* if (px_fmt == TH_PF_444) { int pitch = 3; frame_data.resize(size.x * size.y * pitch); DVector<uint8_t>::Write w = frame_data.write(); char* dst = (char*)w.ptr(); for(int i=0;i<size.y;i++) { char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; char *out = dst + (int)size.x * pitch * i; char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*i; char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*i; for (int j=0;j<size.x;j++) { out[j*3+0] = in_y[j]; out[j*3+1] = in_u[j]; out[j*3+2] = in_v[j]; }; } format = Image::FORMAT_YUV_444; } else { int div; if (px_fmt!=TH_PF_422) { div = 2; } bool rgba = true; if (rgba) { int pitch = 4; frame_data.resize(size.x * size.y * pitch); DVector<uint8_t>::Write w = frame_data.write(); char* dst = (char*)w.ptr(); uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y / div); for(int i=0;i<size.y;i++) { char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*(i/div); char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*(i/div); uint8_t *out = (uint8_t*)dst + (int)size.x * pitch * i; int ofs = 0; for (int j=0;j<size.x;j++) { uint8_t y, u, v; y = in_y[j]; u = in_u[j/2]; v = in_v[j/2]; int32_t r = Math::fast_ftoi(1.164 * (y - 16) + 1.596 * (v - 128)); int32_t g = Math::fast_ftoi(1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128)); int32_t b = Math::fast_ftoi(1.164 * (y - 16) + 2.018 * (u - 128)); out[ofs++] = CLAMP(r, 0, 255); out[ofs++] = CLAMP(g, 0, 255); out[ofs++] = CLAMP(b, 0, 255); out[ofs++] = 255; } } format = Image::FORMAT_RGBA; } else { int pitch = 2; frame_data.resize(size.x * size.y * pitch); DVector<uint8_t>::Write w = frame_data.write(); char* dst = (char*)w.ptr(); uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y / div); for(int i=0;i<size.y;i++) { char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; char *out = dst + (int)size.x * pitch * i; for (int j=0;j<size.x;j++) out[j*2] = in_y[j]; char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*(i/div); char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*(i/div); for (int j=0;j<(int)size.x>>1;j++) { out[j*4+1] = in_u[j]; out[j*4+3] = in_v[j]; } } format = Image::FORMAT_YUV_422; }; }; // */ frames_pending = 1; }
void VideoStreamPlaybackTheora::video_write(void) { th_ycbcr_buffer yuv; th_decode_ycbcr_out(td, yuv); // FIXME: The way stuff is commented out with `//*/` closing comments // sounds very fishy... /* int y_offset, uv_offset; y_offset=(ti.pic_x&~1)+yuv[0].stride*(ti.pic_y&~1); { int pixels = size.x * size.y; frame_data.resize(pixels * 4); PoolVector<uint8_t>::Write w = frame_data.write(); char* dst = (char*)w.ptr(); int p = 0; for (int i=0; i<size.y; i++) { char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; char *out = dst + (int)size.x * 4 * i; for (int j=0;j<size.x;j++) { dst[p++] = in_y[j]; dst[p++] = in_y[j]; dst[p++] = in_y[j]; dst[p++] = 255; }; } format = Image::FORMAT_RGBA8; } //*/ //* int pitch = 4; frame_data.resize(size.x * size.y * pitch); { PoolVector<uint8_t>::Write w = frame_data.write(); char *dst = (char *)w.ptr(); //uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y/2); if (px_fmt == TH_PF_444) { yuv444_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0); } else if (px_fmt == TH_PF_422) { yuv422_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0); } else if (px_fmt == TH_PF_420) { yuv420_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[2].data, (uint8_t *)yuv[1].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0); }; format = Image::FORMAT_RGBA8; } Ref<Image> img = memnew(Image(size.x, size.y, 0, Image::FORMAT_RGBA8, frame_data)); //zero copy image creation texture->set_data(img); //zero copy send to visual server /* if (px_fmt == TH_PF_444) { int pitch = 3; frame_data.resize(size.x * size.y * pitch); PoolVector<uint8_t>::Write w = frame_data.write(); char* dst = (char*)w.ptr(); for(int i=0;i<size.y;i++) { char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; char *out = dst + (int)size.x * pitch * i; char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*i; char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*i; for (int j=0;j<size.x;j++) { out[j*3+0] = in_y[j]; out[j*3+1] = in_u[j]; out[j*3+2] = in_v[j]; }; } format = Image::FORMAT_YUV_444; } else { int div; if (px_fmt!=TH_PF_422) { div = 2; } bool rgba = true; if (rgba) { int pitch = 4; frame_data.resize(size.x * size.y * pitch); PoolVector<uint8_t>::Write w = frame_data.write(); char* dst = (char*)w.ptr(); uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y / div); for(int i=0;i<size.y;i++) { char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*(i/div); char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*(i/div); uint8_t *out = (uint8_t*)dst + (int)size.x * pitch * i; int ofs = 0; for (int j=0;j<size.x;j++) { uint8_t y, u, v; y = in_y[j]; u = in_u[j/2]; v = in_v[j/2]; int32_t r = Math::fast_ftoi(1.164 * (y - 16) + 1.596 * (v - 128)); int32_t g = Math::fast_ftoi(1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128)); int32_t b = Math::fast_ftoi(1.164 * (y - 16) + 2.018 * (u - 128)); out[ofs++] = CLAMP(r, 0, 255); out[ofs++] = CLAMP(g, 0, 255); out[ofs++] = CLAMP(b, 0, 255); out[ofs++] = 255; } } format = Image::FORMAT_RGBA8; } else { int pitch = 2; frame_data.resize(size.x * size.y * pitch); PoolVector<uint8_t>::Write w = frame_data.write(); char* dst = (char*)w.ptr(); uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y / div); for(int i=0;i<size.y;i++) { char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; char *out = dst + (int)size.x * pitch * i; for (int j=0;j<size.x;j++) out[j*2] = in_y[j]; char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*(i/div); char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*(i/div); for (int j=0;j<(int)size.x>>1;j++) { out[j*4+1] = in_u[j]; out[j*4+3] = in_v[j]; } } format = Image::FORMAT_YUV_422; }; }; //*/ frames_pending = 1; }