void RenderThread::RenderFrames(FrameListPtr sourceFrames, YUV_PLANE plane) { FrameImpl tempFrame; for (int i = 0; i < sourceFrames->size(); i++) { FramePtr sourceFrameOrig = sourceFrames->at(i); if (!sourceFrameOrig) { continue; } unsigned int viewID = sourceFrameOrig->Info(VIEW_ID).toUInt(); Frame* sourceFrame = sourceFrameOrig.data(); float scaleX = 1; float scaleY = 1; if (plane != PLANE_COLOR) { COLOR_FORMAT c = sourceFrameOrig->Format()->Color(); if (c == I420 || c == I422 || c == I444) { sourceFrame = &tempFrame; FormatPtr format = sourceFrameOrig->Format(); sourceFrame->Format()->SetColor(Y800); sourceFrame->Format()->SetWidth(format->PlaneWidth(plane)); sourceFrame->Format()->SetHeight(format->PlaneHeight(plane)); sourceFrame->Format()->SetStride(0, format->Stride(plane)); sourceFrame->Format()->PlaneSize(0); sourceFrame->SetData(0, sourceFrameOrig->Data(plane)); scaleX = ((float)format->PlaneWidth(plane))/format->Width(); scaleY = ((float)format->PlaneHeight(plane))/format->Height(); } } int pos = -1; for (int k = 0; k < m_RenderFrames.size(); k++) { FramePtr _frame = m_RenderFrames.at(k); if (_frame && _frame->Info(VIEW_ID).toUInt() == viewID) { pos = k; break; } } if (pos == -1) { pos = m_RenderFrames.size(); m_RenderFrames.append(FramePtr()); } FramePtr& renderFrame = m_RenderFrames[pos]; // Deallocate if resolution changed if (renderFrame && (sourceFrame->Format()->Width() != renderFrame->Format()->Width() || sourceFrame->Format()->Height() != renderFrame->Format()->Height())) { m_Renderer->Deallocate(renderFrame); renderFrame.clear(); } // Allocate if needed if (!renderFrame) { m_Renderer->Allocate(renderFrame, sourceFrame->Format()); } renderFrame->SetInfo(VIEW_ID, viewID); renderFrame->SetInfo(RENDER_SRC_SCALE_X, scaleX); renderFrame->SetInfo(RENDER_SRC_SCALE_Y, scaleY); // Render frame if (m_Renderer->GetFrame(renderFrame) == OK) { if (sourceFrame->Format() == renderFrame->Format()) { for (int i=0; i<4; i++) { size_t len = renderFrame->Format()->PlaneSize(i); if (len > 0) { memcpy(renderFrame->Data(i), sourceFrame->Data(i), len); } } }else { ColorConversion(*sourceFrame, *renderFrame); } m_Renderer->ReleaseFrame(renderFrame); } } }
void ColorConversion(const Frame& in, Frame& out) { const FormatPtr format_in = in.Format(); FormatPtr format_out = out.Format(); int step_in[4]; memcpy(step_in, format_in->Stride(), sizeof(step_in)); unsigned char* data_in[4], *data_out[4]; memcpy(data_in, in.Data(), sizeof(data_in)); memcpy(data_out, out.Data(), sizeof(data_out)); COLOR_FORMAT color_in = format_in->Color(); COLOR_FORMAT color_out = format_out->Color(); if (color_in == IMC2) { color_in = YV12; data_in[2] = data_in[1]+format_in->Width()/2; step_in[2] = step_in[1]; }else if (color_in == IMC4) { color_in = I420; data_in[2] = data_in[1]+format_in->Width()/2; step_in[2] = step_in[1]; }else if (color_in == YVYU) { // Special case since ffmpeg converter doesn't have this by default // Swap chroma plans data_out[3] = data_out[1]; data_out[1] = data_out[2]; data_out[2] = data_out[3]; data_out[3] = 0; } PrepareCC(color_in, data_in); PrepareCC(color_out, data_out); bool ok = false; if (!ok) { // Try FFMpeg conversion if framewave doesn't support the conversion struct SwsContext *ctx = sws_getContext(format_in->Width(), format_in->Height(), YT2FFMpegFormat(color_in), format_out->Width(), format_out->Height(), YT2FFMpegFormat(color_out), SWS_BILINEAR, NULL,NULL,NULL ); if (ctx) { if (sws_scale( ctx, data_in, step_in, 0, format_in->Height(), data_out, format_out->Stride()) == format_out->Height()) { ok = true; } sws_freeContext( ctx ); } } if (!ok) { // Fill with random data for (int i=0; i<4; i++) { for (int j=0; j<format_out->Stride(i)*format_out->Height(); j++) { data_out[i][j] = rand()*255/RAND_MAX; } } } out.SetPTS(in.PTS()); out.SetFrameNumber(in.FrameNumber()); for (int i=0; i<LAST_INFO_KEY; i++) { if (in.HasInfo((INFO_KEY)i)) { out.SetInfo((INFO_KEY)i, in.Info((INFO_KEY)i)); } } }