3 * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
4 * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
5 * Copyright (C) 2016 ray <<user@hostname.org>>
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
25 * Alternatively, the contents of this file may be used under the
26 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
27 * which case the following provisions apply instead of the ones
30 * This library is free software; you can redistribute it and/or
31 * modify it under the terms of the GNU Library General Public
32 * License as published by the Free Software Foundation; either
33 * version 2 of the License, or (at your option) any later version.
35 * This library is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38 * Library General Public License for more details.
40 * You should have received a copy of the GNU Library General Public
41 * License along with this library; if not, write to the
42 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
43 * Boston, MA 02111-1307, USA.
47 * SECTION:element-nxvideodec
49 * FIXME:Describe nxvideodec here.
52 * <title>Example launch line</title>
54 * gst-launch -v -m fakesrc ! nxvideodec ! fakesink silent=TRUE
66 #include <gst/video/video.h>
67 #include <gst/video/gstvideodecoder.h>
68 #include <gstmmvideobuffermeta.h>
69 #include <linux/videodev2.h>
70 #include "gstnxvideodec.h"
71 #include <gst/allocators/gsttizenmemory.h>
73 // This SUPPORT_NO_MEMORY_COPY function is disabled now.
74 // if the video decoder mmap is supported this function, it will be enabled.
75 #define SUPPORT_NO_MEMORY_COPY 1
76 //#define CODEC_DEC_OUTPUT_DUMP 1
78 GST_DEBUG_CATEGORY_STATIC (gst_nxvideodec_debug_category);
79 #define GST_CAT_DEFAULT gst_nxvideodec_debug_category
82 static void gst_nxvideodec_set_property (GObject * object,
83 guint property_id, const GValue * value, GParamSpec * pspec);
84 static void gst_nxvideodec_get_property (GObject * object,
85 guint property_id, GValue * value, GParamSpec * pspec);
87 static gboolean gst_nxvideodec_start (GstVideoDecoder * decoder);
88 static gboolean gst_nxvideodec_stop (GstVideoDecoder * decoder);
89 static gboolean gst_nxvideodec_set_format (GstVideoDecoder * decoder,
90 GstVideoCodecState * state);
91 static gboolean gst_nxvideodec_flush (GstVideoDecoder * decoder);
92 static GstFlowReturn gst_nxvideodec_handle_frame (GstVideoDecoder * decoder,
93 GstVideoCodecFrame * frame);
94 static void nxvideodec_base_init (gpointer gclass);
95 static void nxvideodec_buffer_finalize (gpointer pData);
97 #if SUPPORT_NO_MEMORY_COPY
98 static void nxvideodec_get_offset_stride (gint width, gint height,
99 guint8 * pSrc, gsize * pOffset, gint * pStride);
108 PROP_TYPE //0: 1:MM_VIDEO_BUFFER_TYPE_GEM
124 #define ALIGN(X,N) ( (X+N-1) & (~(N-1)) )
127 struct video_meta_mmap_buffer
130 GstNxVideoDec *pNxVideoDec;
133 #define PLUGIN_LONG_NAME "S5P6818 H/W Video Decoder"
134 #define PLUGIN_DESC "Nexell H/W Video Decoder for S5P6818, Version: 0.1.0"
135 #define PLUGIN_AUTHOR "Hyun Chul Jun <hcjun@nexell.co.kr>"
138 static GstStaticPadTemplate gst_nxvideodec_src_template =
139 GST_STATIC_PAD_TEMPLATE ("src",
142 GST_STATIC_CAPS ("video/x-raw, "
143 "format = (string) { S420 }, "
144 "width = (int) [ 64, 1920 ], " "height = (int) [ 64, 1088 ] ")
148 #ifdef CODEC_DEC_OUTPUT_DUMP /* for decoder output dump */
150 decoder_output_dump (GstBuffer *buffer)
153 char filename[100]={0};
155 tbm_surface_h surface;
156 tbm_surface_info_s info;
157 GstMemory *mem = gst_buffer_peek_memory (buffer, 0);
160 surface = gst_tizen_memory_get_surface(mem);
162 tbm_surface_get_info (surface, &info);
164 temp = info.planes[0].ptr;
166 sprintf(filename, "/tmp/dec_output_dump_%d_%d.yuv", info.width, info.height);
167 fp = fopen(filename, "ab");
173 for (i = 0; i < info.height; i++) {
174 fwrite(temp, info.width, 1, fp);
175 temp += info.planes[0].stride;
178 temp = info.planes[1].ptr;
180 for(i = 0; i < info.height/2 ; i++) {
181 fwrite(temp, info.width/2, 1, fp);
182 temp += info.planes[1].stride;
185 temp = info.planes[2].ptr;
187 for(i = 0; i < info.height/2 ; i++) {
188 fwrite(temp, info.width/2, 1, fp);
189 temp += info.planes[2].stride;
197 nxvideodec_base_init (gpointer gclass)
199 GstElementClass *pElement_class = GST_ELEMENT_CLASS (gclass);
200 GstCaps *pCapslist = NULL;
201 GstNxVideoDecClass *pKlass = GST_NXVIDEODEC_CLASS (pElement_class);
205 gst_element_class_set_details_simple (pElement_class,
206 PLUGIN_LONG_NAME, "Codec/Decoder/Video", PLUGIN_DESC, PLUGIN_AUTHOR);
208 pCapslist = gst_caps_new_empty ();
211 gst_caps_append_structure (pCapslist,
212 gst_structure_new ("video/x-h263",
213 "variant", G_TYPE_STRING, "itu", NULL));
216 gst_caps_append_structure (pCapslist,
217 gst_structure_new ("video/x-h264",
218 "alignment", G_TYPE_STRING, "au",
219 "width", GST_TYPE_INT_RANGE, 64, NX_MAX_WIDTH,
220 "height", GST_TYPE_INT_RANGE, 64, NX_MAX_HEIGHT, NULL));
223 gst_caps_append_structure (pCapslist,
224 gst_structure_new ("video/x-xvid",
225 "width", GST_TYPE_INT_RANGE, 64, NX_MAX_WIDTH,
226 "height", GST_TYPE_INT_RANGE, 64, NX_MAX_HEIGHT, NULL));
230 gst_caps_append_structure (pCapslist,
231 gst_structure_new ("video/mpeg",
232 "mpegversion", GST_TYPE_INT_RANGE, 1, 2,
233 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL));
236 gst_caps_append_structure (pCapslist,
237 gst_structure_new ("video/mpeg",
238 "mpegversion", G_TYPE_INT, 4,
239 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL));
242 gst_caps_append_structure (pCapslist,
243 gst_structure_new ("video/x-divx",
244 "width", GST_TYPE_INT_RANGE, 64, NX_MAX_WIDTH,
245 "height", GST_TYPE_INT_RANGE, 64, NX_MAX_HEIGHT,
246 "divxversion", GST_TYPE_INT_RANGE, 3, 6, NULL));
249 gst_caps_append_structure (pCapslist,
250 gst_structure_new ("video/x-msmpeg",
251 "width", GST_TYPE_INT_RANGE, 64, NX_MAX_WIDTH,
252 "height", GST_TYPE_INT_RANGE, 64, NX_MAX_HEIGHT,
253 "msmpegversion", G_TYPE_INT, 43, NULL));
257 gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, pCapslist);
258 gst_element_class_add_pad_template (pElement_class, pKlass->pSinktempl);
259 gst_element_class_add_pad_template (pElement_class,
260 gst_static_pad_template_get (&gst_nxvideodec_src_template));
265 G_DEFINE_TYPE_WITH_CODE (GstNxVideoDec, gst_nxvideodec, GST_TYPE_VIDEO_DECODER,
266 GST_DEBUG_CATEGORY_INIT (gst_nxvideodec_debug_category, "nxvideodec", 0,
267 "debug category for nxvideodec element"));
269 // class initialization
271 gst_nxvideodec_class_init (GstNxVideoDecClass * pKlass)
275 GObjectClass *pGobjectClass = G_OBJECT_CLASS (pKlass);
276 GstVideoDecoderClass *pVideoDecoderClass = GST_VIDEO_DECODER_CLASS (pKlass);
278 nxvideodec_base_init (pKlass);
280 pGobjectClass->set_property = gst_nxvideodec_set_property;
281 pGobjectClass->get_property = gst_nxvideodec_get_property;
283 pVideoDecoderClass->start = GST_DEBUG_FUNCPTR (gst_nxvideodec_start);
284 pVideoDecoderClass->stop = GST_DEBUG_FUNCPTR (gst_nxvideodec_stop);
286 pVideoDecoderClass->set_format =
287 GST_DEBUG_FUNCPTR (gst_nxvideodec_set_format);
288 pVideoDecoderClass->flush = GST_DEBUG_FUNCPTR (gst_nxvideodec_flush);
289 pVideoDecoderClass->handle_frame =
290 GST_DEBUG_FUNCPTR (gst_nxvideodec_handle_frame);
292 #if SUPPORT_NO_MEMORY_COPY
294 g_object_class_install_property (pGobjectClass,
296 g_param_spec_int ("buffer-type", "buffer-type",
297 "Buffer Type(0:NORMAL 1:MM_VIDEO_BUFFER_TYPE_GEM)", 0, 1,
298 BUFFER_TYPE_GEM, G_PARAM_READWRITE));
305 gst_nxvideodec_init (GstNxVideoDec * pNxVideoDec)
309 GST_DEBUG_OBJECT (pNxVideoDec, "dec_init");
311 // Initialize variables
312 pNxVideoDec->pNxVideoDecHandle = NULL;
313 pNxVideoDec->pInputState = NULL;
314 pNxVideoDec->isState = STOP;
315 #if SUPPORT_NO_MEMORY_COPY
317 pNxVideoDec->bufferType = BUFFER_TYPE_GEM;
319 #ifdef TIZEN_FEATURE_ARTIK530
320 pNxVideoDec->allocator = gst_tizen_allocator_new ();
322 pthread_mutex_init (&pNxVideoDec->mutex, NULL);
328 gst_nxvideodec_set_property (GObject * pObject, guint propertyId,
329 const GValue * pValue, GParamSpec * pPspec)
331 GstNxVideoDec *pNxvideodec = GST_NXVIDEODEC (pObject);
334 GST_DEBUG_OBJECT (pNxvideodec, "set_property");
336 switch (propertyId) {
337 #if SUPPORT_NO_MEMORY_COPY
340 pNxvideodec->bufferType = g_value_get_int (pValue);
344 G_OBJECT_WARN_INVALID_PROPERTY_ID (pObject, propertyId, pPspec);
352 gst_nxvideodec_get_property (GObject * pObject, guint propertyId,
353 GValue * pValue, GParamSpec * pPspec)
355 GstNxVideoDec *pNxvideodec = GST_NXVIDEODEC (pObject);
358 GST_DEBUG_OBJECT (pNxvideodec, "get_property");
360 switch (propertyId) {
361 #if SUPPORT_NO_MEMORY_COPY
364 g_value_set_int (pValue, pNxvideodec->bufferType);
368 G_OBJECT_WARN_INVALID_PROPERTY_ID (pObject, propertyId, pPspec);
376 gst_nxvideodec_start (GstVideoDecoder * pDecoder)
378 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
381 GST_DEBUG_OBJECT (pNxVideoDec, "start");
383 if (pNxVideoDec->pNxVideoDecHandle) {
384 CloseVideoDec (pNxVideoDec->pNxVideoDecHandle);
385 pNxVideoDec->pNxVideoDecHandle = NULL;
388 pNxVideoDec->pNxVideoDecHandle = OpenVideoDec ();
390 if (pNxVideoDec->pNxVideoDecHandle == NULL) {
391 GST_ERROR ("VideoDecHandle is NULL !\n");
395 pthread_mutex_lock (&pNxVideoDec->mutex);
396 pNxVideoDec->isState = PLAY;
397 pthread_mutex_unlock (&pNxVideoDec->mutex);
405 gst_nxvideodec_stop (GstVideoDecoder * pDecoder)
407 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
409 if (pNxVideoDec == NULL) {
410 GST_ERROR ("pDecoder is NULL !\n");
414 GST_DEBUG_OBJECT (pNxVideoDec, "stop");
416 pthread_mutex_lock (&pNxVideoDec->mutex);
417 pNxVideoDec->isState = STOP;
418 pthread_mutex_unlock (&pNxVideoDec->mutex);
420 if (pNxVideoDec->pNxVideoDecHandle->pSem) {
421 VDecSemSignal (pNxVideoDec->pNxVideoDecHandle->pSem);
422 VDecSemDestroy (pNxVideoDec->pNxVideoDecHandle->pSem);
423 pNxVideoDec->pNxVideoDecHandle->pSem = NULL;
426 CloseVideoDec (pNxVideoDec->pNxVideoDecHandle);
428 #ifdef TIZEN_FEATURE_ARTIK530
429 if (pNxVideoDec->allocator) {
430 gst_object_unref (pNxVideoDec->allocator);
431 pNxVideoDec->allocator = NULL;
434 pthread_mutex_destroy (&pNxVideoDec->mutex);
441 gst_nxvideodec_set_format (GstVideoDecoder * pDecoder,
442 GstVideoCodecState * pState)
444 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
445 GstStructure *pStructure = NULL;
446 const gchar *pMimeType = NULL;
447 GstBuffer *pCodecData = NULL;
448 GstVideoCodecState *pOutputState = NULL;
449 NX_VIDEO_DEC_STRUCT *pDecHandle = NULL;
451 #ifdef TIZEN_FEATURE_ARTIK530
452 gboolean bIsFormatChange = FALSE;
457 GST_DEBUG_OBJECT (pNxVideoDec, "set_format");
459 if (pNxVideoDec->pInputState) {
460 gst_video_codec_state_unref (pNxVideoDec->pInputState);
461 pNxVideoDec->pInputState = NULL;
464 pNxVideoDec->pInputState = gst_video_codec_state_ref (pState);
466 // Check Support Codec Type
467 pStructure = gst_caps_get_structure (pNxVideoDec->pInputState->caps, 0);
468 pMimeType = gst_structure_get_name (pStructure);
469 if (pNxVideoDec->pNxVideoDecHandle) {
470 pDecHandle = pNxVideoDec->pNxVideoDecHandle;
475 #ifdef TIZEN_FEATURE_ARTIK530
476 GST_DEBUG_OBJECT (pNxVideoDec, "old %dx%d fps=%d/%d %p",
477 pDecHandle->width, pDecHandle->height,
478 pDecHandle->fpsNum, pDecHandle->fpsDen,
479 pDecHandle->codec_data);
480 GST_DEBUG_OBJECT (pNxVideoDec, "new %dx%d fps=%d/%d %p",
481 GST_VIDEO_INFO_WIDTH (&pState->info),
482 GST_VIDEO_INFO_HEIGHT (&pState->info),
483 GST_VIDEO_INFO_FPS_N (&pState->info),
484 GST_VIDEO_INFO_FPS_D (&pState->info),
488 pDecHandle->width != GST_VIDEO_INFO_WIDTH (&pState->info);
490 pDecHandle->height != GST_VIDEO_INFO_HEIGHT (&pState->info);
491 if (GST_VIDEO_INFO_FPS_N (&pState->info) != 0) {
493 pDecHandle->fpsNum != GST_VIDEO_INFO_FPS_N (&pState->info);
495 pDecHandle->fpsDen != GST_VIDEO_INFO_FPS_D (&pState->info);
497 bIsFormatChange |= pDecHandle->fpsNum != 30;
498 bIsFormatChange |= pDecHandle->fpsDen != 1;
500 bIsFormatChange |= (pDecHandle->codec_data != pState->codec_data);
501 gst_buffer_replace (&pDecHandle->codec_data, pState->codec_data);
502 GST_DEBUG_OBJECT (pNxVideoDec, "format changed=%d", bIsFormatChange);
505 pDecHandle->codecType = FindCodecInfo (pState, pDecHandle);
507 if (pDecHandle->codecType < 0) {
508 GST_ERROR ("Unsupported VideoDecoder Mime Type : %s\n", pMimeType);
512 if (pDecHandle->pExtraData) {
513 g_free (pDecHandle->pExtraData);
514 pDecHandle->pExtraData = NULL;
515 pDecHandle->extraDataSize = 0;
518 pCodecData = pNxVideoDec->pInputState->codec_data;
523 if (!gst_buffer_map (pCodecData, &mapInfo, GST_MAP_READ)) {
524 GST_ERROR ("Cannot map input buffer!\n");
528 if (mapInfo.size > 0 && mapInfo.data) {
529 pDecHandle->pExtraData = (guint8 *) g_malloc (mapInfo.size);
530 pDecHandle->extraDataSize = mapInfo.size;
533 if (FALSE == GetExtraInfo (pDecHandle, (guint8 *) mapInfo.data,
535 gst_buffer_unmap (pCodecData, &mapInfo);
538 gst_buffer_unmap (pCodecData, &mapInfo);
540 GST_LOG ("No Codec Data\n");
543 if (pDecHandle->codecType == V4L2_PIX_FMT_H264) {
544 const gchar *pStr = NULL;
546 if ((pStr = gst_structure_get_string (pStructure, "alignment"))) {
547 if (strcmp (pStr, "au") == 0) {
548 pDecHandle->h264Alignment = H264_PARSE_ALIGN_AU;
549 GST_DEBUG_OBJECT (pNxVideoDec, ">>>>> H264 alignment: au Type.");
550 } else if (strcmp (pStr, "nal") == 0) {
551 pDecHandle->h264Alignment = H264_PARSE_ALIGN_NAL;
552 GST_DEBUG_OBJECT (pNxVideoDec, ">>>>> H264 alignment: nal Type.");
554 GST_DEBUG_OBJECT (pNxVideoDec, "unknown alignment: %s", pStr);
560 gst_video_decoder_set_output_state (pDecoder, GST_VIDEO_FORMAT_S420,
561 pDecHandle->width, pDecHandle->height, pNxVideoDec->pInputState);
563 pOutputState->caps = gst_caps_new_simple ("video/x-raw",
564 "format", G_TYPE_STRING,
565 gst_video_format_to_string (GST_VIDEO_FORMAT_S420), "width", G_TYPE_INT,
566 pDecHandle->width, "height", G_TYPE_INT, pDecHandle->height, "framerate",
567 GST_TYPE_FRACTION, pDecHandle->fpsNum, pDecHandle->fpsDen, NULL);
569 gst_video_codec_state_unref (pOutputState);
571 pNxVideoDec->pNxVideoDecHandle->imgPlaneNum = 1;
572 #if SUPPORT_NO_MEMORY_COPY
573 GST_DEBUG_OBJECT (pNxVideoDec, ">>>>> Accelerable.");
575 if (BUFFER_TYPE_GEM == pNxVideoDec->bufferType) {
576 GST_DEBUG_OBJECT (pNxVideoDec, ">>>>> Accelerable.");
580 ret = gst_video_decoder_negotiate (pDecoder);
583 GST_ERROR ("Fail Negotiate !\n");
587 #ifdef TIZEN_FEATURE_ARTIK530
588 if (!bIsFormatChange) {
593 if (pDecHandle->hCodec) {
594 NX_V4l2DecClose (pDecHandle->hCodec);
595 pDecHandle->hCodec = NULL;
597 if (pDecHandle->pTmpStrmBuf) {
598 g_free (pDecHandle->pTmpStrmBuf);
599 pDecHandle->pTmpStrmBuf = NULL;
602 pDecHandle->bInitialized = FALSE;
606 if (0 != InitVideoDec (pNxVideoDec->pNxVideoDecHandle)) {
616 gst_nxvideodec_flush (GstVideoDecoder * pDecoder)
618 GstNxVideoDec *pNxvideodec = GST_NXVIDEODEC (pDecoder);
622 GST_DEBUG_OBJECT (pNxvideodec, "flush");
624 if (pNxvideodec->pNxVideoDecHandle) {
625 pNxvideodec->pNxVideoDecHandle->bFlush = TRUE;
633 #if SUPPORT_NO_MEMORY_COPY
635 nxvideodec_get_offset_stride (gint width, gint height, guint8 * pSrc,
636 gsize * pOffset, gint * pStride)
646 luStride = ALIGN (width, 32);
647 luVStride = ALIGN (height, 16);
648 cStride = luStride / 2;
649 cVStride = ALIGN (height / 2, 16);
651 pcb = plu + luStride * luVStride;
652 pcr = pcb + cStride * cVStride;
655 pOffset[1] = pcb - plu;
656 pOffset[2] = pcr - plu;
658 pStride[0] = luStride;
659 pStride[1] = cStride;
660 pStride[2] = cStride;
664 gst_nxvideodec_handle_frame (GstVideoDecoder * pDecoder,
665 GstVideoCodecFrame * pFrame)
667 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
668 NX_V4L2DEC_OUT decOut;
669 gint64 timeStamp = 0;
672 gboolean bKeyFrame = FALSE;
674 GstMemory *pTmem = NULL;
675 GstBuffer *pGstbuf = NULL;
676 struct video_meta_mmap_buffer *pMeta = NULL;
678 NX_VID_MEMORY_INFO *pImg = NULL;
679 GstVideoCodecState *pState = NULL;
681 GstVideoMeta *pVmeta = NULL;
684 gsize offset[3] = { 0, };
685 gint stride[3] = { 0, };
689 if (!gst_buffer_map (pFrame->input_buffer, &mapInfo, GST_MAP_READ)) {
690 GST_ERROR ("Cannot map input buffer!");
691 gst_video_codec_frame_unref (pFrame);
692 return GST_FLOW_ERROR;
695 bKeyFrame = GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (pFrame);
698 VideoDecodeFrame (pNxVideoDec->pNxVideoDecHandle, pFrame->input_buffer,
701 gst_buffer_unmap (pFrame->input_buffer, &mapInfo);
702 if (DEC_ERR == ret) {
703 GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp);
704 return gst_video_decoder_drop_frame (pDecoder, pFrame);
705 } else if (DEC_INIT_ERR == ret) {
706 return GST_FLOW_ERROR;
709 if (decOut.dispIdx < 0) {
713 GST_DEBUG_OBJECT (pNxVideoDec, " decOut.dispIdx: %d\n", decOut.dispIdx);
716 (struct video_meta_mmap_buffer *) g_malloc (sizeof (struct
717 video_meta_mmap_buffer));
720 GST_ERROR_OBJECT (pNxVideoDec, "failed to malloc for meta");
721 gst_video_codec_frame_unref (pFrame);
722 return GST_FLOW_ERROR;
726 pMeta->v4l2BufferIdx = decOut.dispIdx;
727 pMeta->pNxVideoDec = pNxVideoDec;
729 pGstbuf = gst_buffer_new ();
731 GST_ERROR_OBJECT (pNxVideoDec, "failed to gst_buffer_new");
732 gst_video_codec_frame_unref (pFrame);
737 nxvideodec_get_offset_stride (pNxVideoDec->pNxVideoDecHandle->width,
738 pNxVideoDec->pNxVideoDecHandle->height, (guint8 *) pImg->pBuffer[0],
741 pState = gst_video_decoder_get_output_state (pDecoder);
743 pTmem = gst_tizen_allocator_alloc_surface (pNxVideoDec->allocator, &pState->info, pImg->surface, pMeta, nxvideodec_buffer_finalize);
746 gst_buffer_add_video_meta_full (pGstbuf, GST_VIDEO_FRAME_FLAG_NONE,
747 GST_VIDEO_INFO_FORMAT (&pState->info),
748 GST_VIDEO_INFO_WIDTH (&pState->info),
749 GST_VIDEO_INFO_HEIGHT (&pState->info), n_planes, offset, stride);
752 GST_ERROR_OBJECT (pNxVideoDec, "failed to gst_buffer_add_video_meta_full");
753 gst_video_codec_state_unref (pState);
754 gst_video_codec_frame_unref (pFrame);
757 gst_buffer_append_memory (pGstbuf, pTmem);
759 #ifdef CODEC_DEC_OUTPUT_DUMP /* for decoder output dump */
760 decoder_output_dump (pGstbuf);
762 pFrame->output_buffer = pGstbuf;
764 if (-1 == GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp)) {
765 GST_DEBUG_OBJECT (pNxVideoDec, "Cannot Found Time Stamp!!!");
767 pFrame->pts = timeStamp;
768 GST_BUFFER_PTS (pFrame->output_buffer) = timeStamp;
770 gst_video_codec_state_unref (pState);
772 ret = gst_video_decoder_finish_frame (pDecoder, pFrame);
784 nxvideodec_buffer_finalize (pMeta);
787 return GST_FLOW_ERROR;
791 gst_nxvideodec_handle_frame (GstVideoDecoder * pDecoder,
792 GstVideoCodecFrame * pFrame)
794 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
795 NX_V4L2DEC_OUT decOut;
796 gint64 timeStamp = 0;
799 gboolean bKeyFrame = FALSE;
800 GstMemory *pGstmem = NULL;
801 GstBuffer *pGstbuf = NULL;
802 struct video_meta_mmap_buffer *pMeta = NULL;
806 if (!gst_buffer_map (pFrame->input_buffer, &mapInfo, GST_MAP_READ)) {
807 GST_ERROR ("Cannot map input buffer!");
808 gst_video_codec_frame_unref (pFrame);
809 return GST_FLOW_ERROR;
812 bKeyFrame = GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (pFrame);
815 VideoDecodeFrame (pNxVideoDec->pNxVideoDecHandle, pFrame->input_buffer,
818 gst_buffer_unmap (pFrame->input_buffer, &mapInfo);
819 if (DEC_ERR == ret) {
820 GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp);
821 return gst_video_decoder_drop_frame (pDecoder, pFrame);
822 } else if (DEC_INIT_ERR == ret) {
823 return GST_FLOW_ERROR;
826 if (decOut.dispIdx < 0) {
830 GST_DEBUG_OBJECT (pNxVideoDec, " decOut.dispIdx: %d\n", decOut.dispIdx);
832 if (BUFFER_TYPE_GEM == pNxVideoDec->bufferType) {
833 pGstbuf = gst_buffer_new ();
835 GST_ERROR_OBJECT (pNxVideoDec, "failed to gst_buffer_new");
836 gst_video_codec_frame_unref (pFrame);
841 (struct video_meta_mmap_buffer *) g_malloc (sizeof (struct
842 video_meta_mmap_buffer));
844 GST_ERROR_OBJECT (pNxVideoDec, "failed to malloc for meta");
845 gst_video_codec_frame_unref (pFrame);
846 return GST_FLOW_ERROR;
848 pMeta->v4l2BufferIdx = decOut.dispIdx;
849 pMeta->pNxVideoDec = pNxVideoDec;
850 pGstmem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
852 sizeof (struct video_meta_mmap_buffer),
854 sizeof (struct video_meta_mmap_buffer),
855 pMeta, nxvideodec_buffer_finalize);
857 GST_ERROR_OBJECT (pNxVideoDec,
858 "failed to gst_memory_new_wrapped for mmap buffer");
859 gst_video_codec_frame_unref (pFrame);
862 gst_buffer_append_memory (pGstbuf, pGstmem);
864 gst_buffer_add_mmvideobuffer_meta (pGstbuf, 0);
866 pFrame->output_buffer = pGstbuf;
868 if (-1 == GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp)) {
869 GST_DEBUG_OBJECT (pNxVideoDec, "Cannot Found Time Stamp!!!");
871 pFrame->pts = timeStamp;
872 GST_BUFFER_PTS (pFrame->output_buffer) = timeStamp;
874 GstVideoFrame videoFrame;
875 NX_VID_MEMORY_INFO *pImg = NULL;
876 guint8 *pPtr = NULL;;
877 GstVideoCodecState *pState = NULL;
878 GstFlowReturn flowRet;
887 flowRet = gst_video_decoder_allocate_output_frame (pDecoder, pFrame);
888 pState = gst_video_decoder_get_output_state (pDecoder);
889 if (flowRet != GST_FLOW_OK) {
890 gst_video_codec_state_unref (pState);
891 gst_video_codec_frame_unref (pFrame);
895 if (!gst_video_frame_map (&videoFrame, &pState->info, pFrame->output_buffer,
897 GST_ERROR ("Cannot video frame map!\n");
898 gst_video_codec_state_unref (pState);
899 gst_video_codec_frame_unref (pFrame);
900 return GST_FLOW_ERROR;
903 if (-1 == GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp)) {
904 GST_DEBUG_OBJECT (pNxVideoDec, "Cannot Found Time Stamp!!!");
906 pFrame->pts = timeStamp;
907 GST_BUFFER_PTS (pFrame->output_buffer) = timeStamp;
910 pPtr = GST_VIDEO_FRAME_COMP_DATA (&videoFrame, 0);
912 luStride = ALIGN (pNxVideoDec->pNxVideoDecHandle->width, 32);
913 luVStride = ALIGN (pNxVideoDec->pNxVideoDecHandle->height, 16);
914 cStride = luStride / 2;
915 cVStride = ALIGN (pNxVideoDec->pNxVideoDecHandle->height / 2, 16);
916 plu = (guint8 *) pImg->pBuffer[0];
917 pcb = plu + luStride * luVStride;
918 pcr = pcb + cStride * cVStride;
920 CopyImageToBufferYV12 ((guint8 *) plu, (guint8 *) pcb, (guint8 *) pcr,
921 pPtr, luStride, cStride, pNxVideoDec->pNxVideoDecHandle->width,
922 pNxVideoDec->pNxVideoDecHandle->height);
924 DisplayDone (pNxVideoDec->pNxVideoDecHandle, decOut.dispIdx);
926 gst_video_frame_unmap (&videoFrame);
927 gst_video_codec_state_unref (pState);
930 ret = gst_video_decoder_finish_frame (pDecoder, pFrame);
941 nxvideodec_buffer_finalize (pMeta);
944 return GST_FLOW_ERROR;
949 nxvideodec_buffer_finalize (gpointer pData)
955 struct video_meta_mmap_buffer *pMeta =
956 (struct video_meta_mmap_buffer *) pData;
959 GST_ERROR ("Error: pData is null !");
963 if ((pMeta->pNxVideoDec) && (pMeta->pNxVideoDec->pNxVideoDecHandle)) {
964 pthread_mutex_lock (&pMeta->pNxVideoDec->mutex);
965 if (PLAY == pMeta->pNxVideoDec->isState) {
966 GST_DEBUG_OBJECT (pMeta->pNxVideoDec, "v4l2BufferIdx: %d\n",
967 pMeta->v4l2BufferIdx);
969 DisplayDone (pMeta->pNxVideoDec->pNxVideoDecHandle,
970 pMeta->v4l2BufferIdx);
972 GST_ERROR ("Fail: DisplayDone !");
975 pthread_mutex_unlock (&pMeta->pNxVideoDec->mutex);
977 GST_ERROR ("Error: hCodec is null !");
986 plugin_init (GstPlugin * plugin)
992 /* FIXME Remember to set the rank if it's an element that is meant
993 to be autoplugged by decodebin. */
994 ret = gst_element_register (plugin, "nxvideodec", GST_RANK_PRIMARY + 1,
995 GST_TYPE_NXVIDEODEC);
1002 #define VERSION "0.1.0"
1005 #define PACKAGE "S5P6818 GStreamer PlugIn"
1007 #ifndef PACKAGE_NAME
1008 #define PACKAGE_NAME "S5P6818 GStreamer PlugIn"
1010 #ifndef GST_PACKAGE_ORIGIN
1011 #define GST_PACKAGE_ORIGIN "http://www.nexell.co.kr"
1014 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1017 "Nexell H/W Video Decoder for S5P6818",
1018 plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN)