/*! \brief This function applies deinterlacing (only if needed) and color conversion to the video frame in fRawDecodedPicture. It is assumed that fRawDecodedPicture wasn't deinterlaced and color converted yet (otherwise this function behaves in unknown manners). You should only call this function when you got a new picture decoded by the video decoder and the fHeader variable was updated accordingly (\see _UpdateMediaHeaderForVideoFrame()). When this function finishes the postprocessed video frame will be available in fPostProcessedDecodedPicture and fDecodedData (fDecodedDataSizeInBytes will be set accordingly). */ void AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame() { int displayWidth = fHeader.u.raw_video.display_line_width; int displayHeight = fHeader.u.raw_video.display_line_count; AVPicture deinterlacedPicture; bool useDeinterlacedPicture = false; if (fRawDecodedPicture->interlaced_frame) { AVPicture rawPicture; rawPicture.data[0] = fRawDecodedPicture->data[0]; rawPicture.data[1] = fRawDecodedPicture->data[1]; rawPicture.data[2] = fRawDecodedPicture->data[2]; rawPicture.data[3] = fRawDecodedPicture->data[3]; rawPicture.linesize[0] = fRawDecodedPicture->linesize[0]; rawPicture.linesize[1] = fRawDecodedPicture->linesize[1]; rawPicture.linesize[2] = fRawDecodedPicture->linesize[2]; rawPicture.linesize[3] = fRawDecodedPicture->linesize[3]; avpicture_alloc(&deinterlacedPicture, fContext->pix_fmt, displayWidth, displayHeight); if (avpicture_deinterlace(&deinterlacedPicture, &rawPicture, fContext->pix_fmt, displayWidth, displayHeight) < 0) { TRACE("[v] avpicture_deinterlace() - error\n"); } else useDeinterlacedPicture = true; } // Some decoders do not set pix_fmt until they have decoded 1 frame #if USE_SWS_FOR_COLOR_SPACE_CONVERSION if (fSwsContext == NULL) { fSwsContext = sws_getContext(displayWidth, displayHeight, fContext->pix_fmt, displayWidth, displayHeight, colorspace_to_pixfmt(fOutputColorSpace), SWS_FAST_BILINEAR, NULL, NULL, NULL); } #else if (fFormatConversionFunc == NULL) { fFormatConversionFunc = resolve_colorspace(fOutputColorSpace, fContext->pix_fmt, displayWidth, displayHeight); } #endif fDecodedDataSizeInBytes = avpicture_get_size( colorspace_to_pixfmt(fOutputColorSpace), displayWidth, displayHeight); if (fDecodedData == NULL) fDecodedData = static_cast<uint8_t*>(malloc(fDecodedDataSizeInBytes)); fPostProcessedDecodedPicture->data[0] = fDecodedData; fPostProcessedDecodedPicture->linesize[0] = fHeader.u.raw_video.bytes_per_row; #if USE_SWS_FOR_COLOR_SPACE_CONVERSION if (fSwsContext != NULL) { #else if (fFormatConversionFunc != NULL) { #endif if (useDeinterlacedPicture) { AVFrame deinterlacedFrame; deinterlacedFrame.data[0] = deinterlacedPicture.data[0]; deinterlacedFrame.data[1] = deinterlacedPicture.data[1]; deinterlacedFrame.data[2] = deinterlacedPicture.data[2]; deinterlacedFrame.data[3] = deinterlacedPicture.data[3]; deinterlacedFrame.linesize[0] = deinterlacedPicture.linesize[0]; deinterlacedFrame.linesize[1] = deinterlacedPicture.linesize[1]; deinterlacedFrame.linesize[2] = deinterlacedPicture.linesize[2]; deinterlacedFrame.linesize[3] = deinterlacedPicture.linesize[3]; #if USE_SWS_FOR_COLOR_SPACE_CONVERSION sws_scale(fSwsContext, deinterlacedFrame.data, deinterlacedFrame.linesize, 0, displayHeight, fPostProcessedDecodedPicture->data, fPostProcessedDecodedPicture->linesize); #else (*fFormatConversionFunc)(&deinterlacedFrame, fPostProcessedDecodedPicture, displayWidth, displayHeight); #endif } else { #if USE_SWS_FOR_COLOR_SPACE_CONVERSION sws_scale(fSwsContext, fRawDecodedPicture->data, fRawDecodedPicture->linesize, 0, displayHeight, fPostProcessedDecodedPicture->data, fPostProcessedDecodedPicture->linesize); #else (*fFormatConversionFunc)(fRawDecodedPicture, fPostProcessedDecodedPicture, displayWidth, displayHeight); #endif } } if (fRawDecodedPicture->interlaced_frame) avpicture_free(&deinterlacedPicture); }
status_t AVCodecDecoder::_NegotiateVideoOutputFormat(media_format* inOutFormat) { TRACE("AVCodecDecoder::_NegotiateVideoOutputFormat()\n"); fOutputVideoFormat = fInputFormat.u.encoded_video.output; fContext->width = fOutputVideoFormat.display.line_width; fContext->height = fOutputVideoFormat.display.line_count; // fContext->frame_rate = (int)(fOutputVideoFormat.field_rate // * fContext->frame_rate_base); fOutputFrameRate = fOutputVideoFormat.field_rate; fContext->extradata = (uint8_t*)fExtraData; fContext->extradata_size = fExtraDataSize; TRACE(" requested video format 0x%x\n", inOutFormat->u.raw_video.display.format); // Make MediaPlayer happy (if not in rgb32 screen depth and no overlay, // it will only ask for YCbCr, which DrawBitmap doesn't handle, so the // default colordepth is RGB32). if (inOutFormat->u.raw_video.display.format == B_YCbCr422) fOutputVideoFormat.display.format = B_YCbCr422; else fOutputVideoFormat.display.format = B_RGB32; // Search for a pixel-format the codec handles // TODO: We should try this a couple of times until it succeeds, each // time using another pixel-format that is supported by the decoder. // But libavcodec doesn't seem to offer any way to tell the decoder // which format it should use. #if USE_SWS_FOR_COLOR_SPACE_CONVERSION if (fSwsContext != NULL) sws_freeContext(fSwsContext); fSwsContext = NULL; #else fFormatConversionFunc = 0; #endif // Iterate over supported codec formats for (int i = 0; i < 1; i++) { // close any previous instance if (fCodecInitDone) { fCodecInitDone = false; avcodec_close(fContext); } // TODO: Set n-th fContext->pix_fmt here if (avcodec_open(fContext, fCodec) >= 0) { fCodecInitDone = true; #if USE_SWS_FOR_COLOR_SPACE_CONVERSION fSwsContext = sws_getContext(fContext->width, fContext->height, fContext->pix_fmt, fContext->width, fContext->height, colorspace_to_pixfmt(fOutputVideoFormat.display.format), SWS_FAST_BILINEAR, NULL, NULL, NULL); } #else fFormatConversionFunc = resolve_colorspace( fOutputVideoFormat.display.format, fContext->pix_fmt, fContext->width, fContext->height); } if (fFormatConversionFunc != NULL) break; #endif }