1697d1cf43319013a7c2de9e763b65240f4baff8
1 /*
2 * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
3 *
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * Neither the name of Texas Instruments Incorporated nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
35 #ifdef HAVE_CONFIG_H
36 # include <config.h>
37 #endif
39 #include <gst/gst.h>
41 #include <gst/video/gstvideopool.h>
42 #include "gsth265dec.h"
43 #include <malloc.h>
44 #include "gsth265utils.h"
45 #include "gsth265buf.h"
46 #ifdef PROFILE
47 #include <sys/time.h>
48 #endif
50 GST_DEBUG_CATEGORY_STATIC (gst_h265dec_debug);
51 #define GST_CAT_DEFAULT gst_h265dec_debug
53 #define H265_MAX_WIDTH 1920
54 #define H265_MAX_HEIGHT 1080
55 /* Global variables */
56 volatile guint32 nDecFrmNo;
57 volatile gint32 nFrameDecodeStart ;
58 volatile gint32 nFrameDecodeEnd;
59 volatile gint32 nTerminateStatus ;
60 volatile guint32 nFrameSync ;
61 volatile guint32 nFrameSyncSlave ;
62 volatile guint32 nFlushCall ;
63 volatile static guint8 nCnt ;
64 volatile guint32 nDecodeEnd ;
65 volatile static guint32 nDecodeComplete ;
66 guint32 nValidBytesLeft ;
67 guint32 nNumThreads ;
68 guint8 nGlobalDataBuffer[((H265_MAX_WIDTH*H265_MAX_HEIGHT*3 )>>1) + 40960];
69 guint32 nDispFrmNo ;
70 gint32 nTOTAL_FRAME_SIZE;
71 tPP_H265_DynamicParams h265_DynamicParams;
72 tPPDecParam_Status apVal ;
73 tPPBaseDecoder *h265dec = NULL;
74 BUFFMGR_buffEleHandle H265_dec_BuffEle ;
75 tPPInFrame_Buff H265_dec_InBuff;
76 tPPOutFrame_Buff H265_dec_OutBuff;
77 tPPInput_BitStream H265InputStream ;
78 tPPInput_BitStream H265InputStreamNAL ;
79 tPP_H265_CreateParams h265_CreateParams;
80 tPPQueryMemRecords ReqMemTab[PP_H265DEC_MAX_MEMTAB];
81 tPPYUVPlanarDisplayFrame pOutBuf[PP_H265VDEC_MAX_REF_FRAMES + 1];
82 tPPInGst_Buff GstBufOut[PP_H265VDEC_MAX_REF_FRAMES + 1];
83 GstMapInfo info_out;
84 tPPGstNAL aGstNAL;
85 /* Thread identifiers */
86 pthread_t thread[4];
87 gint32 *pThreadRetVal[3] ;
88 gint32 taskid[4] = {0};
89 guint8 pTempData[((H265_MAX_WIDTH*H265_MAX_HEIGHT*3 )>>1)];
91 #ifdef PROFILE
92 struct timeval tProcessSt, tProcessEd;
93 unsigned long long process_time ;
94 unsigned long long total_time ;
95 float frame_rate;
96 unsigned int nFrmNo;
97 #endif
99 /* Id numbers for each thread */
100 /* Filter signals and args */
101 enum
102 {
103 /* FILL ME */
104 LAST_SIGNAL
105 };
107 enum
108 {
109 PROP_0,
110 PROP_SILENT,
111 PROP_THREADS
112 };
114 /* the capabilities of the inputs and outputs.
115 *
116 * describe the real formats here.
117 */
118 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
119 GST_PAD_SINK,
120 GST_PAD_ALWAYS,
121 GST_STATIC_CAPS ("ANY")
122 );
124 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
125 GST_PAD_SRC,
126 GST_PAD_ALWAYS,
127 GST_STATIC_CAPS ("ANY")
128 );
130 #define gst_h265dec_parent_class parent_class
131 G_DEFINE_TYPE (Gsth265dec, gst_h265dec, GST_TYPE_ELEMENT);
133 static void gst_h265dec_set_property (GObject * object, guint prop_id,
134 const GValue * value, GParamSpec * pspec);
136 static void gst_h265dec_get_property (GObject * object, guint prop_id,
137 GValue * value, GParamSpec * pspec);
139 static gboolean gst_h265dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event);
140 static GstFlowReturn gst_h265dec_chain (GstPad * pad,
141 GstObject * parent, GstBuffer * buf);
142 static void*
143 gst_h265dec_process_call(void *pInputStream);
145 void gH265_InterleaveChroma_armv7(guint8 *Indata,
146 guint8 *OutData , gint32 nWidth,
147 gint32 nHeight);
149 /* initialize the h265dec's class */
150 static void
151 gst_h265dec_class_init (Gsth265decClass * klass)
152 {
153 GObjectClass *gobject_class;
154 GstElementClass *gstelement_class;
156 gobject_class = (GObjectClass *) klass;
157 gstelement_class = (GstElementClass *) klass;
159 gobject_class->set_property = gst_h265dec_set_property;
160 gobject_class->get_property = gst_h265dec_get_property;
162 g_object_class_install_property (gobject_class, PROP_SILENT,
163 g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
164 FALSE, G_PARAM_READWRITE));
166 g_object_class_install_property (gobject_class, PROP_THREADS,
167 g_param_spec_int ("threads", "Threads", "Number of threads",
168 1, 4, 4, G_PARAM_READWRITE));
169 gst_element_class_set_details_simple(gstelement_class,
170 "H265 Decoder ",
171 "Codec/Decoder/Video",
172 "Decodes H265 streams",
173 "pathpartner <<pathpartner@pathpartner.org>>");
175 gst_element_class_add_pad_template (gstelement_class,
176 gst_static_pad_template_get (&src_factory));
178 gst_element_class_add_pad_template (gstelement_class,
179 gst_static_pad_template_get (&sink_factory));
180 }
182 /* initialize the new element
183 * instantiate pads and add them to element
184 * set pad calback functions
185 * initialize instance structure
186 */
187 static void
188 gst_h265dec_init (Gsth265dec * decoder)
189 {
190 decoder->sinkpad
191 = gst_pad_new_from_static_template (&sink_factory, "sink");
192 gst_pad_set_event_function (decoder->sinkpad,
193 GST_DEBUG_FUNCPTR(gst_h265dec_sink_event));
194 gst_pad_set_chain_function (decoder->sinkpad,
195 GST_DEBUG_FUNCPTR(gst_h265dec_chain));
196 GST_PAD_SET_PROXY_CAPS (decoder->sinkpad);
197 gst_element_add_pad (GST_ELEMENT (decoder), decoder->sinkpad);
198 decoder->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
199 GST_PAD_SET_PROXY_CAPS (decoder->srcpad);
200 gst_element_add_pad (GST_ELEMENT (decoder), decoder->srcpad);
201 decoder->nInitFlag = 0;
202 decoder->silent = FALSE;
203 }
205 static void
206 gst_h265dec_set_property (GObject * object, guint prop_id,
207 const GValue * value, GParamSpec * pspec)
208 {
209 Gsth265dec *decoder = GST_H265DEC (object);
211 switch (prop_id)
212 {
213 case PROP_SILENT:
214 decoder->silent = g_value_get_boolean (value);
215 break;
216 case PROP_THREADS:
217 decoder->threads = g_value_get_int (value);
218 break;
219 default:
220 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
221 break;
222 }
223 }
225 static void
226 gst_h265dec_get_property (GObject * object, guint prop_id,
227 GValue * value, GParamSpec * pspec)
228 {
229 Gsth265dec *decoder = GST_H265DEC (object);
231 switch (prop_id) {
232 case PROP_SILENT:
233 g_value_set_boolean (value, decoder->silent);
234 break;
236 case PROP_THREADS:
237 g_value_set_int (value , decoder->threads);
238 break;
240 default:
241 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
242 break;
243 }
244 }
246 /* GstElement vmethod implementations */
248 /* this function handles sink events */
249 static gboolean
250 gst_h265dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
251 {
252 gboolean ret;
253 Gsth265dec *decoder;
255 decoder = GST_H265DEC (parent);
257 switch (GST_EVENT_TYPE (event)) {
258 case GST_EVENT_CAPS:
259 {
260 GstCaps * caps;
262 gst_event_parse_caps (event, &caps);
263 /* do something with the caps */
265 /* and forward */
266 ret = gst_pad_event_default (pad, parent, event);
267 break;
268 }
269 default:
270 ret = gst_pad_event_default (pad, parent, event);
271 break;
272 }
273 return ret;
274 }
275 /*
276 ******************************************************************************
277 * @fn sPP_H265_MultiThreadInit(tPPi32 argc, tPPi8 *argv[])
278 *
279 * @brief Function to initialize multi thread parameters
280 *
281 * @param nMultiThreadParam [IN] Structure
282 *
283 * @return Number of bytes written to the file
284 ******************************************************************************
285 */
286 static gint32 sPP_H265_MultiThreadInit(tPPMultiThreadParams *nMultiThreadParam,
287 guint32 nThreadID,
288 guint32 nNumThd)
289 {
290 /*Task ID*/
291 if(nThreadID == 0)
292 nMultiThreadParam->nTaskID = kH265_TASK_MASTER ;
293 else
294 nMultiThreadParam->nTaskID = kH265_TASK_SLAVE ;
295 /*Number of threads*/
296 nMultiThreadParam->nNumThreads = nNumThd ;
297 /*Thread ID */
298 nMultiThreadParam->nThreadID = nThreadID ;
300 return GST_FLOW_OK ;
301 }
303 static GstCaps *
304 gst_h265dec_getcaps (GstPad * pad)
305 {
306 GstCaps *caps = NULL;
307 caps = gst_pad_get_current_caps (pad);
308 if (caps == NULL) {
309 GstCaps *fil = gst_pad_get_pad_template_caps (pad);
310 g_print("gst_pad_get_current_caps Failing\n");
311 return gst_caps_copy (fil);
312 } else {
313 return gst_caps_copy (caps);
314 }
315 }
317 /* chain function
318 * this function does the actual processing
319 */
320 static GstFlowReturn
321 gst_h265dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
322 {
323 Gsth265dec *decoder;
324 GstMapInfo info ;
325 guint32 taskidMaster = 0;
326 gint32 nRetVal;
327 gint32 aByteConsumed = 0;
328 gint32 nOffset = 0;
329 gint32 i;
330 gint32 nFlag = 0;
331 guint32 nIndex ,nIndex1;
332 guint32 nNumMemTabEntries =0;
333 guint32 nRet;
334 guint32 nDispFlag;
335 GstQuery *query = NULL;
336 guint min = 0;
337 guint max = 0;
338 guint size = 0;
339 GstCaps *Caps;
340 GstStructure *config;
341 GstFlowReturn flow;
342 GstBuffer *pVpeBuff = NULL;
343 GstBuffer *GstOutBufTemp;
345 decoder = GST_H265DEC (parent);
347 gst_buffer_map(buf, &info , GST_MAP_READ);
349 H265InputStream.nBufLength = info.size;
350 H265InputStreamNAL.nBufLength = info.size;
352 nOffset = nValidBytesLeft;
353 nDispFlag = 1;
354 /* Initialiazations */
355 if(!decoder->nInitFlag)
356 {
357 /* H265 decoder initialization*/
358 FUNC_MEMSET(ReqMemTab, 0,
359 sizeof(tPPQueryMemRecords)*PP_H265DEC_MAX_MEMTAB);
361 nRetVal = 0;
362 h265_CreateParams.nNumThreads = decoder->threads;
363 h265_CreateParams.nMaxWidth = H265_MAX_WIDTH;
364 h265_CreateParams.nMaxHeight = H265_MAX_HEIGHT;
365 nNumThreads = decoder->threads;
366 decoder->nTimeStamp = 0;
368 nRetVal = gPP_H265_QueryMemoryRequirements( &ReqMemTab[0],
369 &h265_CreateParams, &nNumMemTabEntries);
371 /* Increase default malloc size */
372 mallopt(M_MMAP_THRESHOLD , (1024*1024*30));
374 /*Allocate the memory*/
375 nRetVal = MEMMGR_AllocMemoryRequirements(&ReqMemTab[0],
376 nNumMemTabEntries);
378 if(nRetVal != GST_FLOW_OK)
379 {
380 g_print("Error in Allocating the memory requirements.\n");
381 }
383 /*Pass the memory and Initialize the decoder*/
384 nRetVal = gPP_H265_InitializeDecoder (&h265dec,
385 &ReqMemTab[0],&h265_CreateParams);
387 h265_DynamicParams.nDecodeHeader = PP_H265_PARSE_HEADER;
389 if(nRetVal != GST_FLOW_OK)
390 {
391 g_print("Error in Initializing \n");
392 }
394 /* Initialise pLum pointers in output base frames to NULL.
395 * When the decoder initialises these pointers with valid values we know
396 * that its time to dump/display them
397 */
398 nIndex = 0;
399 while( nIndex < (PP_H265VDEC_MAX_REF_FRAMES+1) )
400 {
401 pOutBuf[nIndex].pLum = NULL;
402 nIndex++;
403 }
405 for(i = 1; i < nNumThreads; i++)
406 {
407 taskid[i] = i;
408 /* Create a thread with its argument in taskid[i] */
409 nRet = pthread_create(&thread[i], NULL,
410 &gst_h265dec_process_call, &taskid[i]);
411 if (nRet)
412 {
413 /* Check for errors */
414 printf("ERROR; return code from pthread_create() is %d\n",
415 nRet);
416 }
417 }
418 if(!gst_pad_has_current_caps(decoder->srcpad))
419 g_print("gst_pad_has_current_caps Failing\n");
421 Caps = gst_h265dec_getcaps (decoder->srcpad);
422 if(Caps == NULL)
423 g_print("gst_pad_get_current_caps Failing\n");
426 query =
427 gst_query_new_allocation ( Caps, TRUE);
429 if (gst_pad_peer_query (decoder->srcpad, query))
430 {
431 g_print("gst_pad_peer_query sucessful\n");
432 }
433 else
434 {
435 g_print("gst_pad_peer_query failed\n");
436 }
438 if (gst_query_get_n_allocation_pools (query) > 0) {
439 /* we got configuration from our peer, parse them */
440 gst_query_parse_nth_allocation_pool (query, 0, &decoder->externalpool, &size,
441 &min, &max);
442 }
443 else
444 {
445 decoder->externalpool = NULL;
446 size = 0;
447 min = max = 0;
448 }
450 if (decoder->externalpool == NULL) {
451 /* we did not get a pool, make one ourselves then */
452 decoder->externalpool = gst_video_buffer_pool_new ();
453 }
455 config = gst_buffer_pool_get_config (decoder->externalpool);
456 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
457 gst_buffer_pool_config_set_params (config, Caps, size, min, max);
458 gst_buffer_pool_set_config (decoder->externalpool, config);
460 /* and activate */
461 gst_buffer_pool_set_active (decoder->externalpool, TRUE);
462 decoder->nInitFlag = 1;
463 }
465 for(i = 0 ; i < info.size ;i++)
466 {
467 nGlobalDataBuffer[i + nOffset] = info.data[i];
468 }
470 H265InputStream.nBitStream =
471 H265InputStreamNAL.nBitStream = &nGlobalDataBuffer[0];
473 H265InputStreamNAL.nBufLength = (info.size) + nOffset;
474 /* Default buffer size*/
475 if(info.size < 4096 )
476 {
477 nFlag = 1;
478 }
480 do
481 {
482 aByteConsumed = 0;
483 /* Parse frame data*/
484 nRetVal = gH265_ParseNALUnitFrame(&aGstNAL,
485 H265InputStreamNAL , &aByteConsumed);
487 if(nRetVal == SC_PP_NEXT_FRAME_FOUND )
488 {
489 H265InputStream.nBufLength = aByteConsumed;
490 H265InputStream.nBitStream = H265InputStreamNAL.nBitStream;
491 /* if frame data decode */
492 gst_h265dec_process_call(&taskidMaster);
494 H265InputStreamNAL.nBitStream += aByteConsumed;
495 H265InputStreamNAL.nBufLength -= aByteConsumed;
497 }
498 else if(nFlag)
499 {
500 H265InputStream.nBufLength = aByteConsumed;
501 H265InputStream.nBitStream = H265InputStreamNAL.nBitStream;
502 /* if frame data decode */
503 gst_h265dec_process_call(&taskidMaster);
505 /* File sink */
506 nIndex = 0;
508 while( nIndex < (PP_H265VDEC_MAX_REF_FRAMES + 1) )
509 {
510 if (pOutBuf[nIndex].pLum)
511 {
512 nIndex1 =0;
513 while(nIndex1 < (PP_H265VDEC_MAX_REF_FRAMES + 1) )
514 {
515 if(GstBufOut[nIndex1].GstDispBuf == NULL)
516 {
517 nIndex1++;
518 continue;
519 }
521 if( pOutBuf[nIndex].pLum == GstBufOut[nIndex1].Out_map.data)
522 {
523 /* Conversion of YUV data to NV12 format */
524 gH265_InterleaveChroma_armv7(GstBufOut[nIndex1].\
525 Out_map.data, pTempData, apVal.nPicWidth,
526 apVal.nPicHeight);
528 flow = gst_buffer_pool_acquire_buffer (decoder->externalpool, &pVpeBuff, NULL);
530 if (flow != GST_FLOW_OK)
531 {
532 GST_INFO_OBJECT (decoder, "couldn't allocate output buffer, flow %s",
533 gst_flow_get_name (flow));
534 }
535 gst_buffer_fill(pVpeBuff, 0, pTempData,
536 ((nTOTAL_FRAME_SIZE * 3) >> 1));
538 nRet = gst_pad_push (decoder->srcpad,
539 pVpeBuff);
541 nDispFrmNo++;
542 pOutBuf[nIndex].pLum = NULL;
543 break;
544 }
545 nIndex1++;
546 }
547 }
548 else
549 {
550 break;
551 }
552 nIndex++;
553 /*Call release buffer*/
554 BUFFMGR_ReleaseBufID(&H265_dec_OutBuff.bufId[0], GstBufOut );
555 }
557 nFlushCall = 1;
558 gst_h265dec_process_call(&taskidMaster);
560 while(nDecodeComplete != (nNumThreads - 1) );
561 /* Deallocate the memory*/
562 MEMMGR_DeAllocMemory(&ReqMemTab[0]);
564 for(i = 0; i < (nNumThreads - 1); i++)
565 {
566 pthread_join(thread[(i + 1)] ,
567 (void **)&pThreadRetVal[i]);
568 }
569 H265InputStreamNAL.nBitStream += aByteConsumed;
570 H265InputStreamNAL.nBufLength -= aByteConsumed;
571 }
572 else
573 {
574 for(i= 0 ; i< H265InputStreamNAL.nBufLength ;i++ )
575 {
576 nGlobalDataBuffer[i] = H265InputStreamNAL.nBitStream [i];
577 }
578 nValidBytesLeft = H265InputStreamNAL.nBufLength;
579 break;
580 }
582 /* File sink */
583 nIndex = 0;
585 while( nIndex < (PP_H265VDEC_MAX_REF_FRAMES + 1) )
586 {
587 if (pOutBuf[nIndex].pLum)
588 {
589 nIndex1 =0;
590 while(nIndex1 < (PP_H265VDEC_MAX_REF_FRAMES + 1) )
591 {
592 if(GstBufOut[nIndex1].GstDispBuf == NULL)
593 {
594 nIndex1++;
595 continue;
596 }
598 if( pOutBuf[nIndex].pLum == GstBufOut[nIndex1].Out_map.data)
599 {
600 /* Conversion of YUV data to NV12 format */
601 gH265_InterleaveChroma_armv7(GstBufOut[nIndex1].\
602 Out_map.data, pTempData, apVal.nPicWidth,
603 apVal.nPicHeight);
605 flow = gst_buffer_pool_acquire_buffer (decoder->externalpool, &pVpeBuff, NULL);
607 if (flow != GST_FLOW_OK)
608 {
609 GST_INFO_OBJECT (decoder, "couldn't allocate output buffer, flow %s",
610 gst_flow_get_name (flow));
611 }
613 gst_buffer_fill(pVpeBuff, 0, pTempData,
614 ((nTOTAL_FRAME_SIZE * 3) >> 1));
616 nRet = gst_pad_push (decoder->srcpad,
617 pVpeBuff);
619 nDispFrmNo++;
620 pOutBuf[nIndex].pLum = NULL;
621 break;
622 }
623 nIndex1++;
624 }
625 }
626 else
627 {
628 break;
629 }
630 nIndex++;
631 /*Call release buffer*/
632 BUFFMGR_ReleaseBufID(&H265_dec_OutBuff.bufId[0], GstBufOut );
633 }
634 }while(H265InputStreamNAL.nBufLength > 3);
636 if(nFlag && nDispFlag)
637 {
638 #ifdef PROFILE
639 g_print(" Total decode time : %lld.%lld ms\n",
640 total_time/1000,total_time%1000);
641 frame_rate = (nDecFrmNo * (1000000))/(float)total_time;
642 g_print(" Frames per second : %0.2f fps\n",frame_rate);
643 #endif
644 nDispFlag = 0;
645 }
646 return 0;
648 }
650 static void*
651 gst_h265dec_process_call(void* thread_args)
652 {
653 gint32 nRetVal ,nRetV;
654 gint32 *thread_ptr = (gint32 *)thread_args;
655 gint32 thread_no = *thread_ptr;
656 /*MultiThread*/
657 tPPMultiThreadParams nMultiThreadParam;
658 guint32 BuffID;
660 nRetVal = sPP_H265_MultiThreadInit(&nMultiThreadParam ,
661 thread_no, nNumThreads);
663 if(nRetVal != SC_PP_SUCCESS)
664 {
665 printf("Invalid Multi thread init params\n");
666 goto EXIT_H265DEC;
667 }
668 START_FRAME:
669 /* Multithread synchronization*/
670 gPP_PPL_AtomicAdd8((guint8 *)&nFrameSyncSlave, 1);
671 while((nFrameSyncSlave % nNumThreads) != 0) ;
673 if(!nFlushCall)
674 {
675 if (nMultiThreadParam.nTaskID == kH265_TASK_MASTER)
676 {
677 /* h265_DynamicParams.nDecodeHeader = PP_H265_PARSE_HEADER;*/
679 nRetV = h265dec->vSet(h265dec, PP_SET_DECODE_HDR,
680 h265_DynamicParams.nDecodeHeader, &h265_DynamicParams);
682 if(nRetV == EC_PP_FAILURE)
683 {
684 nTerminateStatus = 1;
685 goto EXIT_H265DEC;
686 }
687 if(h265_DynamicParams.nDecodeHeader == PP_H265_PARSE_HEADER)
688 {
689 guint8 *pBitStream ;
690 gint32 nBitLen;
692 pBitStream = H265InputStream.nBitStream ;
693 nBitLen = H265InputStream.nBufLength ;
694 nRetVal = h265dec->vDecode(h265dec,
695 &(H265InputStream), &(H265_dec_InBuff),
696 &(H265_dec_OutBuff),
697 (tPPYUVPlanarDisplayFrame *)(&pOutBuf[0]),
698 &nMultiThreadParam);
700 H265InputStream.nBitStream = pBitStream +
701 (nBitLen - H265InputStream.nBufLength);
703 nRetVal = h265dec->vGet(h265dec,
704 PP_GET_PARAMSTATUS, (void *)(&apVal));
705 }
707 h265_DynamicParams.nDecodeHeader = PP_H265_DECODE_ACCESSUNIT;
709 nRetV = h265dec->vSet(h265dec, PP_SET_DECODE_HDR,
710 h265_DynamicParams.nDecodeHeader, &h265_DynamicParams);
712 if(h265_DynamicParams.nDecodeHeader ==
713 PP_H265_DECODE_ACCESSUNIT)
714 {
715 BuffID = BUFFMGR_GetFreeBufID(GstBufOut);
717 nTOTAL_FRAME_SIZE =(apVal.nPicWidth * apVal.nPicHeight);
719 /* Assign the buffer allotted by Buffer manager to I/p frame*/
720 if(BuffID < (PP_H265VDEC_MAX_REF_FRAMES+1))
721 {
722 GstBufOut[BuffID - 1].GstDispBuf =
723 gst_buffer_new_allocate(NULL,
724 ((nTOTAL_FRAME_SIZE * 3) >>1), NULL);
725 if(GST_IS_BUFFER(GstBufOut[BuffID - 1].GstDispBuf))
726 {
727 gst_buffer_map(GstBufOut[BuffID - 1].GstDispBuf,
728 &GstBufOut[BuffID - 1].Out_map , GST_MAP_WRITE) ;
729 }
730 (H265_dec_InBuff.buf[0])=
731 GstBufOut[BuffID - 1].Out_map.data;
732 (H265_dec_InBuff.buf[1])=
733 (H265_dec_InBuff.buf[0])+ nTOTAL_FRAME_SIZE;
734 (H265_dec_InBuff.buf[2])=
735 (H265_dec_InBuff.buf[1]) + (nTOTAL_FRAME_SIZE >>2);
736 (H265_dec_InBuff.bufId) = BuffID;
737 }
738 else
739 {
740 printf("No Free Buffers available\n");
741 nTerminateStatus = 1;
742 }
743 }
744 }
745 gPP_PPL_AtomicAdd8((guint8 *)&nFrameSync, 1);
747 while((nFrameSync % nNumThreads) != 0)
748 {
749 if(nTerminateStatus == 1)
750 {
751 goto EXIT_H265DEC;
752 }
753 };
754 if (nMultiThreadParam.nTaskID == kH265_TASK_MASTER)
755 {
756 #ifdef PROFILE
757 gettimeofday(&tProcessSt , NULL) ;
758 #endif
759 }
760 nRetVal = h265dec->vDecode(h265dec,
761 &(H265InputStream), &(H265_dec_InBuff),
762 &(H265_dec_OutBuff), (tPPYUVPlanarDisplayFrame *)(&pOutBuf[0]),
763 &nMultiThreadParam);
765 if (nMultiThreadParam.nTaskID == kH265_TASK_MASTER)
766 {
767 #ifdef PROFILE
768 gettimeofday(&tProcessEd , NULL) ;
769 process_time = (tProcessEd.tv_sec - tProcessSt.tv_sec)*1000000 +
770 (tProcessEd.tv_usec - tProcessSt.tv_usec);
771 total_time += process_time;
772 #endif
773 }
774 if(nRetVal == EC_PP_FAILURE)
775 {
776 if(nMultiThreadParam.nTaskID == kH265_TASK_MASTER)
777 {
778 goto EXIT_H265DEC;
779 }
780 }
781 if(nMultiThreadParam.nTaskID == kH265_TASK_MASTER)
782 {
783 nCnt = 0;
784 nFrameSyncSlave = 0;
785 nFrameSync = 0;
787 h265dec->vGet( h265dec,
788 PP_GET_ERRORSTATUS,(void *)(&apVal));
790 if(nDecFrmNo >= 0)
791 {
792 gint32 nTemp =0;
793 h265dec->vGet( h265dec, PP_GET_BUFSTATUS,
794 (void *)(&nTemp));
795 if((nTemp == BUFFMGR_FREE) || (nTemp == BUFFMGR_USED))
796 {
797 if(h265_DynamicParams.nDecodeHeader ==
798 PP_H265_DECODE_ACCESSUNIT)
799 {
800 GstBufOut->bufStatus = (BUFFMGR_BufferStatus)nTemp;
801 }
802 }
803 }
805 /* If the end of NAL unit(Start of the next NAL unit)
806 not found exit*/
807 if( nRetVal == EC_PP_H265_NO_NALU_END_FOUND )
808 {
809 printf("\nError : NAL unit's end not found\n");
810 goto EXIT_H265DEC;
811 }
813 if ( ( nRetVal == EC_PP_FAILURE )
814 ||( nRetVal == EC_PP_INVALID_PARAM ) ||
815 (nRetVal == EC_PP_NOT_SUPPORTED) )
816 {
817 printf(" Invalid parameters\n");
818 }
819 /* If complete frame is decoded, write that in the output file*/
820 if( nRetVal == SC_PP_SUCCESS || nRetVal == SC_PP_RESOLUTION_CHANGED
821 || nRetVal == SC_PP_END_OF_PICTURE)
822 {
823 nDecFrmNo++;
824 }/*end of if( nRetVal == SC_PP_SUCCESS )*/
825 }/*end of if(nMultiThreadParam.nTaskID == kH265_TASK_MASTER)*/
827 if (nMultiThreadParam.nTaskID != kH265_TASK_MASTER)
828 {
829 if (( nRetVal == EC_PP_FAILURE ) ||
830 (nRetVal == EC_PP_INVALID_PARAM ) ||
831 (nRetVal == EC_PP_NOT_SUPPORTED) ||
832 (nRetVal == EC_PP_H265_NO_NALU_END_FOUND))
833 {
834 goto EXIT_H265DEC ;
835 }
837 gPP_PPL_AtomicAdd8((guint8 *)&nFrameDecodeStart,1);
838 do
839 {
840 if(nFrameDecodeStart == (nNumThreads -1))
841 {
842 gPP_PPL_AtomicAdd8((guint8 *)&nFrameDecodeEnd,1);
843 break;
844 }
845 }while(1);
846 }
847 if (nMultiThreadParam.nTaskID == kH265_TASK_MASTER)
848 {
849 do
850 {
851 if(nFrameDecodeEnd == (nNumThreads -1))
852 {
853 nFrameDecodeStart = 0;
854 nFrameDecodeEnd = 0;
855 break;
856 }
857 }
858 while(1);
859 }
860 else
861 {
862 while(nFrameDecodeStart);
863 }
865 if (nMultiThreadParam.nTaskID != kH265_TASK_MASTER)
866 {
867 goto START_FRAME;
868 }
869 }
870 else
871 {
872 /*Flush Call*/
873 if (nMultiThreadParam.nTaskID == kH265_TASK_MASTER)
874 {
875 /* after Decoding Last Frame Dump all the rest frame */
876 do
877 {
878 h265dec->vSet(h265dec ,
879 PP_SET_DPB_FLUSH , PP_TRUE, &h265_DynamicParams);
881 nRetVal = h265dec->vDecode(h265dec,
882 &(H265InputStream),
883 &(H265_dec_InBuff),
884 &(H265_dec_OutBuff),
885 (tPPYUVPlanarDisplayFrame *)(&pOutBuf[0]),
886 &nMultiThreadParam);
888 }while (nRetVal == SC_PP_SUCCESS);
889 }
890 }
891 EXIT_H265DEC:
892 {
893 if (nMultiThreadParam.nTaskID != kH265_TASK_MASTER)
894 {
895 gPP_PPL_AtomicAdd8((guint8 *)&nDecodeComplete,1);
896 pthread_exit(&nMultiThreadParam.nThreadID);
897 }
898 /* Multithread synchronization*/
899 }
900 return GST_FLOW_OK;
901 }
903 /* entry point to initialize the plug-in
904 * initialize the plug-in itself
905 * register the element factories and other features
906 */
907 static gboolean
908 h265dec_init (GstPlugin * h265dec)
909 {
910 /* debug category for fltering log messages
911 *
912 * exchange the string 'Template h265dec' with your description
913 */
914 GST_DEBUG_CATEGORY_INIT (gst_h265dec_debug, "h265dec",
915 0, "H265dec decoder");
917 return gst_element_register (h265dec, "h265dec", GST_RANK_NONE,
918 GST_TYPE_H265DEC);
919 }
921 /* PACKAGE: this is usually set by autotools depending on some _INIT macro
922 * in configure.ac and then written into and defined in config.h, but we can
923 * just set it ourselves here in case someone doesn't use autotools to
924 * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
925 */
926 #ifndef PACKAGE
927 #define PACKAGE "myfirsth265dec"
928 #endif
930 /* gstreamer looks for this structure to register h265decs
931 *
932 * exchange the string 'Template h265dec' with your h265dec description
933 */
934 GST_PLUGIN_DEFINE (
935 GST_VERSION_MAJOR,
936 GST_VERSION_MINOR,
937 h265dec,
938 "H265dec decoder",
939 h265dec_init,
940 "1.0.0",
941 "BSD-3-Clause",
942 "GStreamer",
943 "http://gstreamer.net/"
944 )