Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //icaclient/develop/main/UKH/NetClient/main/linux/obj.h264/FFDecode.cpp#13 - edit change 297198 (ktext)
- /*****************************************************************************
- *
- * FFDecode.cpp
- *
- * H.264 v3 interface software fallback implementation.
- *
- * $Id: //icaclient/unix13.3/client/unix/CitrixPluginSDK/H264_sample/FFDecode.cpp#1 $
- *
- * Copyright 2013-2015 Citrix Systems, Inc. All Rights Reserved.
- *
- *****************************************************************************/
- #include <dlfcn.h>
- #include <linux/limits.h>
- #include "FFDecode.h"
- #define X11_SUPPORT // For now ...
- #ifdef X11_SUPPORT
- #include <X11/Xlib.h>
- #endif /* X11_SUPPORT */
- static int buffer_open(URLContext* h, const char* buffname, int flags);
- static int buffer_read(URLContext* h, unsigned char *buf, int size);
- static int buffer_close(URLContext* h);
- // Globals.
- URLProtocol buffer_protocol = {
- "buffer", // name
- buffer_open, // open
- buffer_read, // read
- NULL, // write
- NULL, // seek
- buffer_close, // close
- NULL, // next
- NULL, // read_pause
- NULL, // read_seek
- NULL, // get_file_handle
- };
- AVInputFormat *g_pH264Fmt = NULL;
- AVFrame *g_pAVFrame = NULL;
- AVFormatContext *g_pFormatCtx = NULL;
- HSO g_pAVUtil;
- DLFFMPEG_FORMAT g_FFLibFormat;
- DLFFMPEG_CODEC g_FFLibCodec;
- DLFFMPEG_SWSCALE g_FFLibSwScale;
- PFFMPEG_FORMAT_CALL_TABLE g_pFFMPEGFormatCallTable = NULL;
- PFFMPEG_CODEC_CALL_TABLE g_pFFMPEGCodecCallTable = NULL;
- PFFMPEG_SWSCALE_CALL_TABLE g_pFFMPEGSwscaleCallTable = NULL;
- BYTE DefaultH264MagicBytes[H264_NAL_UNIT_DELIM_SIZE] = {0, 0, 0, 1, 33, 225};
- static HSO OpenDll(const char *ICARoot, const char* pDll);
- static void LoadPreReqFunctions(const char *ICARoot)
- {
- g_pAVUtil = OpenDll(ICARoot, "libavutil.so");
- if (g_pAVUtil) {
- /* Set logging level to QUIET unless instructed otherwise. */
- if (!getenv("CTXH264_FB_FFMPEGLOGGING")) {
- PFN_av_log_set_level p_av_log_set_level;
- p_av_log_set_level =
- (PFN_av_log_set_level)dlsym(g_pAVUtil, "av_log_set_level");
- if (p_av_log_set_level) {
- p_av_log_set_level(AV_LOG_QUIET);
- }
- }
- }
- g_FFLibCodec.dll = OpenDll(ICARoot, "libavcodec.so");
- g_FFLibFormat.dll = OpenDll(ICARoot, "libavformat.so");
- g_FFLibSwScale.dll = OpenDll(ICARoot, "libswscale.so");
- GET_FN_ADDR(g_FFLibCodec, avcodec_init);
- GET_FN_ADDR(g_FFLibCodec, avcodec_find_decoder);
- GET_FN_ADDR(g_FFLibCodec, avcodec_open);
- GET_FN_ADDR(g_FFLibCodec, avcodec_alloc_frame);
- GET_FN_ADDR(g_FFLibCodec, avcodec_decode_video);
- // GET_FN_ADDR(g_FFLibCodec, avpicture_get_size);
- GET_FN_ADDR(g_FFLibCodec, avpicture_fill);
- GET_FN_ADDR(g_FFLibCodec, avcodec_close);
- GET_FN_ADDR(g_FFLibFormat, av_register_all);
- GET_FN_ADDR(g_FFLibFormat, av_find_input_format);
- GET_FN_ADDR(g_FFLibFormat, av_open_input_file);
- GET_FN_ADDR(g_FFLibFormat, av_find_stream_info);
- GET_FN_ADDR(g_FFLibFormat, av_read_frame);
- // GET_FN_ADDR(g_FFLibFormat, av_destruct_packet);
- GET_FN_ADDR(g_FFLibFormat, av_register_protocol);
- GET_FN_ADDR(g_FFLibFormat, av_free);
- GET_FN_ADDR(g_FFLibFormat, av_close_input_file);
- GET_FN_ADDR(g_FFLibSwScale, sws_getContext);
- GET_FN_ADDR(g_FFLibSwScale, sws_scale);
- g_pFFMPEGCodecCallTable = &g_FFLibCodec.fns;
- g_pFFMPEGFormatCallTable = &g_FFLibFormat.fns;
- g_pFFMPEGSwscaleCallTable = &g_FFLibSwScale.fns;
- }
- #define av_register_all \
- (g_pFFMPEGFormatCallTable->pfn_av_register_all)
- #define av_register_protocol \
- (g_pFFMPEGFormatCallTable->pfn_av_register_protocol)
- #define av_find_input_format \
- (g_pFFMPEGFormatCallTable->pfn_av_find_input_format)
- #define av_open_input_file \
- (g_pFFMPEGFormatCallTable->pfn_av_open_input_file)
- #define av_find_stream_info \
- (g_pFFMPEGFormatCallTable->pfn_av_find_stream_info)
- #define av_read_frame \
- (g_pFFMPEGFormatCallTable->pfn_av_read_frame)
- #define av_free \
- (g_pFFMPEGFormatCallTable->pfn_av_free)
- #define av_close_input_file \
- (g_pFFMPEGFormatCallTable->pfn_av_close_input_file)
- #define avcodec_init \
- (g_pFFMPEGCodecCallTable->pfn_avcodec_init)
- #define avcodec_open \
- (g_pFFMPEGCodecCallTable->pfn_avcodec_open)
- #define avcodec_find_decoder \
- (g_pFFMPEGCodecCallTable->pfn_avcodec_find_decoder)
- #define avcodec_alloc_frame \
- (g_pFFMPEGCodecCallTable->pfn_avcodec_alloc_frame)
- #define avpicture_fill \
- (g_pFFMPEGCodecCallTable->pfn_avpicture_fill)
- #define avcodec_decode_video \
- (g_pFFMPEGCodecCallTable->pfn_avcodec_decode_video)
- #define avcodec_close \
- (g_pFFMPEGCodecCallTable->pfn_avcodec_close)
- #define sws_scale \
- (g_pFFMPEGSwscaleCallTable->pfn_sws_scale)
- #define sws_getContext \
- (g_pFFMPEGSwscaleCallTable->pfn_sws_getContext)
- static int buffer_open(URLContext* h, const char* buffname, int flags)
- {
- REFERENCE_VAR (flags);
- // h->priv_data is of type BufferContext. It will be used in FFMPEG src.
- h->priv_data = (void *)buffname;
- return 0;
- }
- static int buffer_read(URLContext* h, unsigned char* buf, int size)
- {
- int iRet = size;
- BufferContext *pBufferCtx = (BufferContext *)h->priv_data;
- REFERENCE_VAR(buf);
- if (size <= (pBufferCtx->iBufferSize - pBufferCtx->iBytesRead)) {
- pBufferCtx->iBytesRead += size;
- } else {
- iRet = -1;
- }
- return iRet;
- }
- static int buffer_close(URLContext* h)
- {
- REFERENCE_VAR(h);
- return 0;
- }
- static HSO OpenDll(const char *ICARoot, const char* pDll)
- {
- HSO hShared;
- char DllPath[PATH_MAX];
- sprintf(DllPath, "%s/%s", ICARoot, pDll);
- hShared = dlopen(DllPath, RTLD_NOLOAD);
- if (hShared != NULL) {
- return hShared;
- }
- hShared = dlopen(DllPath, RTLD_NOW | RTLD_GLOBAL);
- return hShared;
- }
- static void InitOnce(FFMPEGCtx *pCtx, UINT32 uWidth, UINT32 uHeight)
- {
- BufferContext *pBufferCtx = &pCtx->BufferCtx;
- AVCodec *pCodec;
- AVCodecContext *pCodecCtx = NULL;
- pBufferCtx->iBufferSize += H264_NAL_UNIT_DELIM_SIZE;
- av_open_input_file(&pCtx->pFormatCtx, (const char *)pBufferCtx,
- g_pH264Fmt, 0, NULL);
- av_find_stream_info(pCtx->pFormatCtx);
- // Find the first video stream.
- for (unsigned int i = 0; i < pCtx->pFormatCtx->nb_streams; i++) {
- pCodecCtx = pCtx->pFormatCtx->streams[i]->codec;
- if (pCodecCtx->codec_type == CODEC_TYPE_VIDEO) {
- pCtx->VideoStreamIdx = i;
- pCtx->pCodecCtx = pCodecCtx;
- break;
- }
- }
- if (pCodecCtx) {
- // Find the decoder for the video stream. It should be CODEC_ID_H264.
- pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
- avcodec_open(pCodecCtx, pCodec);
- /* Use SWS_FAST_BILINEAR over SWS_BICUBIC: no noticeable
- * image degradation but should perform better.
- */
- pCtx->pImgConvCtx = sws_getContext(uWidth, uHeight, pCodecCtx->pix_fmt,
- uWidth, uHeight,
- PIX_FMT_BGRA, SWS_FAST_BILINEAR,
- NULL, NULL, NULL);
- } else {
- pCodec = NULL;
- }
- pCtx->pCodec = pCodec;
- }
- static bool ff_decode(FFMPEGCtx *pCtx, PBYTE pInData, UINT32 uInSize,
- UINT32 uWidth, UINT32 uHeight)
- {
- int temp = 0;
- BufferContext *pBufferCtx = &pCtx->BufferCtx;
- uInSize -= H264_NAL_UNIT_DELIM_SIZE; /* Discount extra allocation. */
- pBufferCtx->iBufferSize = uInSize;
- pBufferCtx->pBufferAddress = pInData;
- memcpy(pCtx->ActualMagicBytes, pInData, H264_NAL_UNIT_DELIM_SIZE);
- /* Append the Magic Bytes to source. */
- memcpy(pInData + uInSize, DefaultH264MagicBytes, H264_NAL_UNIT_DELIM_SIZE);
- /* Check for one time init. */
- if (pCtx->pFormatCtx == NULL) {
- InitOnce(pCtx, uWidth, uHeight);
- } else {
- PBYTE pNewBuf = pInData;
- /* Skip initial Frame Delimiter. */
- pNewBuf += H264_NAL_UNIT_DELIM_SIZE;
- pBufferCtx->pBufferAddress = pNewBuf;
- pCtx->pFormatCtx->pb->buffer_size = uInSize;
- pCtx->pFormatCtx->pb->buffer = pNewBuf;
- }
- AVPacket *pPacket = &pCtx->CtxAVPacket;
- av_read_frame(pCtx->pFormatCtx, pPacket);
- memcpy(pPacket->data, pCtx->ActualMagicBytes, H264_NAL_UNIT_DELIM_SIZE);
- avcodec_decode_video(pCtx->pCodecCtx, pCtx->pFrameYUV, &temp,
- pPacket->data, pPacket->size);
- if (pPacket->destruct != NULL) {
- pPacket->data = NULL;
- pPacket->size = 0;
- }
- pBufferCtx->iBytesRead = 0;
- return temp ? true : false;
- }
- bool ff_decode_yuv(FFMPEGCtx *pCtx, PBYTE pInData, UINT32 uInSize,
- char *data, int *offsets, int *pitches,
- UINT32 uWidth, UINT32 uHeight)
- {
- if (ff_decode(pCtx, pInData, uInSize, uWidth, uHeight)) {
- UINT32 y;
- AVPicture *p = (AVPicture *)pCtx->pFrameYUV;
- /* Copy full resolution Y (luminance) channel. */
- for (y = 0; y < uHeight; y++) {
- memcpy(&data[offsets[0] + (y * pitches[0])],
- &p->data[0][y * p->linesize[0]], pitches[0]);
- }
- /* Copy U and V planes (each having quarter resolution). */
- for (y = 0; y < uHeight / 2; y++) {
- memcpy(&data[offsets[1] + (y * pitches[1])],
- &p->data[1][y * p->linesize[1]], pitches[1]);
- memcpy(&data[offsets[2] + (y * pitches[2])],
- &p->data[2][y * p->linesize[2]], pitches[2]);
- }
- return true;
- }
- return false;
- }
- #ifdef X11_SUPPORT
- bool ff_decode_rgb(FFMPEGCtx* pCtx, PBYTE pInData, UINT32 uInSize,
- XImage *img, UINT32 uWidth, UINT32 uHeight)
- {
- if (ff_decode(pCtx, pInData, uInSize, uWidth, uHeight)) {
- avpicture_fill((AVPicture*)pCtx->pFrameBGRA, (uint8_t *)img->data,
- PIX_FMT_BGRA, uWidth, uHeight);
- pCtx->pFrameBGRA->linesize[0] =
- (pCtx->pFrameBGRA->linesize[0] + 3) & ~3;
- /* Convert the image from its native format to BGR24 */
- sws_scale(pCtx->pImgConvCtx, &pCtx->pFrameYUV->data[0],
- &pCtx->pFrameYUV->linesize[0], 0, uHeight,
- &pCtx->pFrameBGRA->data[0], &pCtx->pFrameBGRA->linesize[0]);
- return true;
- }
- return false;
- }
- #endif /* X11_SUPPORT */
- FFMPEGCtx *ff_open_ctx()
- {
- FFMPEGCtx *pCtx= new FFMPEGCtx;
- memset(pCtx, 0, sizeof(*pCtx));
- strcpy(&pCtx->BufferCtx.szProtoName[0], "buffer:");
- pCtx->pFrameYUV = avcodec_alloc_frame();
- pCtx->pFrameBGRA = avcodec_alloc_frame();
- return pCtx;
- }
- void ff_close_ctx(FFMPEGCtx *pCtx)
- {
- av_free(pCtx->pFrameYUV);
- av_free(pCtx->pFrameBGRA);
- avcodec_close(pCtx->pCodecCtx);
- pCtx->pFormatCtx->pb->buffer = NULL;
- pCtx->pFormatCtx->pb->buffer_size = 0;
- pCtx->pFormatCtx->pb->buf_ptr = NULL;
- pCtx->pFormatCtx->pb->buf_end = NULL;
- pCtx->pFormatCtx->pb->opaque = 0;
- av_close_input_file(pCtx->pFormatCtx);
- delete pCtx;
- }
- void ff_init(const char *ICARoot)
- {
- LoadPreReqFunctions(ICARoot);
- avcodec_init();
- av_register_all();
- av_register_protocol(&buffer_protocol);
- g_pH264Fmt = av_find_input_format("h264");
- }
- void ff_end(void)
- {
- if (g_FFLibSwScale.dll)
- dlclose(g_FFLibSwScale.dll);
- if (g_FFLibFormat.dll)
- dlclose(g_FFLibFormat.dll);
- if (g_FFLibCodec.dll)
- dlclose(g_FFLibCodec.dll);
- if (g_pAVUtil)
- dlclose(g_pAVUtil);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement