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"
72 // This SUPPORT_NO_MEMORY_COPY function is disabled now.
73 // if the video decoder mmap is supported this function, it will be enabled.
74 #define SUPPORT_NO_MEMORY_COPY 1
75 //#define CODEC_DEC_OUTPUT_DUMP 1
77 GST_DEBUG_CATEGORY_STATIC (gst_nxvideodec_debug_category);
78 #define GST_CAT_DEFAULT gst_nxvideodec_debug_category
81 static void gst_nxvideodec_set_property (GObject * object,
82 guint property_id, const GValue * value, GParamSpec * pspec);
83 static void gst_nxvideodec_get_property (GObject * object,
84 guint property_id, GValue * value, GParamSpec * pspec);
86 static gboolean gst_nxvideodec_start (GstVideoDecoder * decoder);
87 static gboolean gst_nxvideodec_stop (GstVideoDecoder * decoder);
88 static gboolean gst_nxvideodec_set_format (GstVideoDecoder * decoder,
89 GstVideoCodecState * state);
90 static gboolean gst_nxvideodec_flush (GstVideoDecoder * decoder);
91 static GstFlowReturn gst_nxvideodec_handle_frame (GstVideoDecoder * decoder,
92 GstVideoCodecFrame * frame);
93 static void nxvideodec_base_init (gpointer gclass);
94 static void nxvideodec_buffer_finalize (gpointer pData);
95 static GstMemory *nxvideodec_mmvideobuf_copy (GstNxVideoDec *pNxVideoDec, NX_V4L2DEC_OUT * pDecOut);
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(MMVideoBuffer *outbuf)
152 char *temp = (char *)outbuf->data[0];
154 char filename[100]={0};
158 GST_ERROR ("codec dec output dump start. w = %d, h = %d", outbuf->width[0], outbuf->height[0]);
160 sprintf(filename, "/tmp/dec_output_dump_%d_%d.yuv", outbuf->width[0], outbuf->height[0]);
161 fp = fopen(filename, "ab");
163 for (i = 0; i < outbuf->height[0]; i++) {
164 ret = fwrite(temp, outbuf->width[0], 1, fp);
165 temp += outbuf->stride_width[0];
168 temp = outbuf->data[1];
169 for (i = 0; i < outbuf->height[0]/2; i++) {
170 ret = fwrite(temp, outbuf->width[0]/2, 1, fp);
171 temp += outbuf->stride_width[0]/2;
174 temp = outbuf->data[2];
175 for (i = 0; i < outbuf->height[0]/2; i++) {
176 ret = fwrite(temp, outbuf->width[0]/2, 1, fp);
177 temp += outbuf->stride_width[0]/2;
180 GST_ERROR ("codec dec output dumped!! ret = %d", ret);
186 nxvideodec_base_init (gpointer gclass)
188 GstElementClass *pElement_class = GST_ELEMENT_CLASS (gclass);
189 GstCaps *pCapslist = NULL;
190 GstNxVideoDecClass *pKlass = GST_NXVIDEODEC_CLASS (pElement_class);
194 gst_element_class_set_details_simple (pElement_class,
195 PLUGIN_LONG_NAME, "Codec/Decoder/Video", PLUGIN_DESC, PLUGIN_AUTHOR);
197 pCapslist = gst_caps_new_empty ();
200 gst_caps_append_structure (pCapslist,
201 gst_structure_new ("video/x-h263",
202 "variant", G_TYPE_STRING, "itu", NULL));
205 gst_caps_append_structure (pCapslist,
206 gst_structure_new ("video/x-h264",
207 "alignment", G_TYPE_STRING, "au",
208 "width", GST_TYPE_INT_RANGE, 64, NX_MAX_WIDTH,
209 "height", GST_TYPE_INT_RANGE, 64, NX_MAX_HEIGHT, NULL));
212 gst_caps_append_structure (pCapslist,
213 gst_structure_new ("video/x-xvid",
214 "width", GST_TYPE_INT_RANGE, 64, NX_MAX_WIDTH,
215 "height", GST_TYPE_INT_RANGE, 64, NX_MAX_HEIGHT, NULL));
219 gst_caps_append_structure (pCapslist,
220 gst_structure_new ("video/mpeg",
221 "mpegversion", GST_TYPE_INT_RANGE, 1, 2,
222 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL));
225 gst_caps_append_structure (pCapslist,
226 gst_structure_new ("video/mpeg",
227 "mpegversion", G_TYPE_INT, 4,
228 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL));
231 gst_caps_append_structure (pCapslist,
232 gst_structure_new ("video/x-divx",
233 "width", GST_TYPE_INT_RANGE, 64, NX_MAX_WIDTH,
234 "height", GST_TYPE_INT_RANGE, 64, NX_MAX_HEIGHT,
235 "divxversion", GST_TYPE_INT_RANGE, 3, 6, NULL));
238 gst_caps_append_structure (pCapslist,
239 gst_structure_new ("video/x-msmpeg",
240 "width", GST_TYPE_INT_RANGE, 64, NX_MAX_WIDTH,
241 "height", GST_TYPE_INT_RANGE, 64, NX_MAX_HEIGHT,
242 "msmpegversion", G_TYPE_INT, 43, NULL));
246 gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, pCapslist);
247 gst_element_class_add_pad_template (pElement_class, pKlass->pSinktempl);
248 gst_element_class_add_pad_template (pElement_class,
249 gst_static_pad_template_get (&gst_nxvideodec_src_template));
254 G_DEFINE_TYPE_WITH_CODE (GstNxVideoDec, gst_nxvideodec, GST_TYPE_VIDEO_DECODER,
255 GST_DEBUG_CATEGORY_INIT (gst_nxvideodec_debug_category, "nxvideodec", 0,
256 "debug category for nxvideodec element"));
258 // class initialization
260 gst_nxvideodec_class_init (GstNxVideoDecClass * pKlass)
264 GObjectClass *pGobjectClass = G_OBJECT_CLASS (pKlass);
265 GstVideoDecoderClass *pVideoDecoderClass = GST_VIDEO_DECODER_CLASS (pKlass);
267 nxvideodec_base_init (pKlass);
269 pGobjectClass->set_property = gst_nxvideodec_set_property;
270 pGobjectClass->get_property = gst_nxvideodec_get_property;
272 pVideoDecoderClass->start = GST_DEBUG_FUNCPTR (gst_nxvideodec_start);
273 pVideoDecoderClass->stop = GST_DEBUG_FUNCPTR (gst_nxvideodec_stop);
275 pVideoDecoderClass->set_format =
276 GST_DEBUG_FUNCPTR (gst_nxvideodec_set_format);
277 pVideoDecoderClass->flush = GST_DEBUG_FUNCPTR (gst_nxvideodec_flush);
278 pVideoDecoderClass->handle_frame =
279 GST_DEBUG_FUNCPTR (gst_nxvideodec_handle_frame);
281 #if SUPPORT_NO_MEMORY_COPY
283 g_object_class_install_property (pGobjectClass,
285 g_param_spec_int ("buffer-type", "buffer-type",
286 "Buffer Type(0:NORMAL 1:MM_VIDEO_BUFFER_TYPE_GEM)", 0, 1,
287 BUFFER_TYPE_GEM, G_PARAM_READWRITE));
294 gst_nxvideodec_init (GstNxVideoDec * pNxVideoDec)
298 GST_DEBUG_OBJECT (pNxVideoDec, "dec_init");
300 // Initialize variables
301 pNxVideoDec->pNxVideoDecHandle = NULL;
302 pNxVideoDec->pInputState = NULL;
303 pNxVideoDec->isState = STOP;
304 #if SUPPORT_NO_MEMORY_COPY
306 pNxVideoDec->bufferType = BUFFER_TYPE_GEM;
308 pthread_mutex_init (&pNxVideoDec->mutex, NULL);
314 gst_nxvideodec_set_property (GObject * pObject, guint propertyId,
315 const GValue * pValue, GParamSpec * pPspec)
317 GstNxVideoDec *pNxvideodec = GST_NXVIDEODEC (pObject);
320 GST_DEBUG_OBJECT (pNxvideodec, "set_property");
322 switch (propertyId) {
323 #if SUPPORT_NO_MEMORY_COPY
326 pNxvideodec->bufferType = g_value_get_int (pValue);
330 G_OBJECT_WARN_INVALID_PROPERTY_ID (pObject, propertyId, pPspec);
338 gst_nxvideodec_get_property (GObject * pObject, guint propertyId,
339 GValue * pValue, GParamSpec * pPspec)
341 GstNxVideoDec *pNxvideodec = GST_NXVIDEODEC (pObject);
344 GST_DEBUG_OBJECT (pNxvideodec, "get_property");
346 switch (propertyId) {
347 #if SUPPORT_NO_MEMORY_COPY
350 g_value_set_int (pValue, pNxvideodec->bufferType);
354 G_OBJECT_WARN_INVALID_PROPERTY_ID (pObject, propertyId, pPspec);
362 gst_nxvideodec_start (GstVideoDecoder * pDecoder)
364 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
367 GST_DEBUG_OBJECT (pNxVideoDec, "start");
369 if (pNxVideoDec->pNxVideoDecHandle) {
370 CloseVideoDec (pNxVideoDec->pNxVideoDecHandle);
371 pNxVideoDec->pNxVideoDecHandle = NULL;
374 pNxVideoDec->pNxVideoDecHandle = OpenVideoDec ();
376 if (pNxVideoDec->pNxVideoDecHandle == NULL) {
377 GST_ERROR ("VideoDecHandle is NULL !\n");
381 pthread_mutex_lock (&pNxVideoDec->mutex);
382 pNxVideoDec->isState = PLAY;
383 pthread_mutex_unlock (&pNxVideoDec->mutex);
391 gst_nxvideodec_stop (GstVideoDecoder * pDecoder)
393 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
395 if (pNxVideoDec == NULL) {
396 GST_ERROR ("pDecoder is NULL !\n");
400 GST_DEBUG_OBJECT (pNxVideoDec, "stop");
402 pthread_mutex_lock (&pNxVideoDec->mutex);
403 pNxVideoDec->isState = STOP;
404 pthread_mutex_unlock (&pNxVideoDec->mutex);
406 if (pNxVideoDec->pNxVideoDecHandle->pSem) {
407 VDecSemSignal (pNxVideoDec->pNxVideoDecHandle->pSem);
408 VDecSemDestroy (pNxVideoDec->pNxVideoDecHandle->pSem);
409 pNxVideoDec->pNxVideoDecHandle->pSem = NULL;
412 CloseVideoDec (pNxVideoDec->pNxVideoDecHandle);
414 pthread_mutex_destroy (&pNxVideoDec->mutex);
421 gst_nxvideodec_set_format (GstVideoDecoder * pDecoder,
422 GstVideoCodecState * pState)
424 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
425 GstStructure *pStructure = NULL;
426 const gchar *pMimeType = NULL;
427 GstBuffer *pCodecData = NULL;
428 GstVideoCodecState *pOutputState = NULL;
429 NX_VIDEO_DEC_STRUCT *pDecHandle = NULL;
431 #ifdef TIZEN_FEATURE_ARTIK530
432 gboolean bIsFormatChange = FALSE;
437 GST_DEBUG_OBJECT (pNxVideoDec, "set_format");
439 if (pNxVideoDec->pInputState) {
440 gst_video_codec_state_unref (pNxVideoDec->pInputState);
441 pNxVideoDec->pInputState = NULL;
444 pNxVideoDec->pInputState = gst_video_codec_state_ref (pState);
446 // Check Support Codec Type
447 pStructure = gst_caps_get_structure (pNxVideoDec->pInputState->caps, 0);
448 pMimeType = gst_structure_get_name (pStructure);
449 if (pNxVideoDec->pNxVideoDecHandle) {
450 pDecHandle = pNxVideoDec->pNxVideoDecHandle;
455 #ifdef TIZEN_FEATURE_ARTIK530
456 GST_DEBUG_OBJECT (pNxVideoDec, "old %dx%d fps=%d/%d %p",
457 pDecHandle->width, pDecHandle->height,
458 pDecHandle->fpsNum, pDecHandle->fpsDen,
459 pDecHandle->codec_data);
460 GST_DEBUG_OBJECT (pNxVideoDec, "new %dx%d fps=%d/%d %p",
461 GST_VIDEO_INFO_WIDTH (&pState->info),
462 GST_VIDEO_INFO_HEIGHT (&pState->info),
463 GST_VIDEO_INFO_FPS_N (&pState->info),
464 GST_VIDEO_INFO_FPS_D (&pState->info),
468 pDecHandle->width != GST_VIDEO_INFO_WIDTH (&pState->info);
470 pDecHandle->height != GST_VIDEO_INFO_HEIGHT (&pState->info);
471 if (GST_VIDEO_INFO_FPS_N (&pState->info) != 0) {
473 pDecHandle->fpsNum != GST_VIDEO_INFO_FPS_N (&pState->info);
475 pDecHandle->fpsDen != GST_VIDEO_INFO_FPS_D (&pState->info);
477 bIsFormatChange |= pDecHandle->fpsNum != 30;
478 bIsFormatChange |= pDecHandle->fpsDen != 1;
480 bIsFormatChange |= (pDecHandle->codec_data != pState->codec_data);
481 gst_buffer_replace (&pDecHandle->codec_data, pState->codec_data);
482 GST_DEBUG_OBJECT (pNxVideoDec, "format changed=%d", bIsFormatChange);
485 pDecHandle->codecType = FindCodecInfo (pState, pDecHandle);
487 if (pDecHandle->codecType < 0) {
488 GST_ERROR ("Unsupported VideoDecoder Mime Type : %s\n", pMimeType);
492 if (pDecHandle->pExtraData) {
493 g_free (pDecHandle->pExtraData);
494 pDecHandle->pExtraData = NULL;
495 pDecHandle->extraDataSize = 0;
498 pCodecData = pNxVideoDec->pInputState->codec_data;
503 if (!gst_buffer_map (pCodecData, &mapInfo, GST_MAP_READ)) {
504 GST_ERROR ("Cannot map input buffer!\n");
508 if (mapInfo.size > 0 && mapInfo.data) {
509 pDecHandle->pExtraData = (guint8 *) g_malloc (mapInfo.size);
510 pDecHandle->extraDataSize = mapInfo.size;
513 if (FALSE == GetExtraInfo (pDecHandle, (guint8 *) mapInfo.data,
515 gst_buffer_unmap (pCodecData, &mapInfo);
518 gst_buffer_unmap (pCodecData, &mapInfo);
520 GST_LOG ("No Codec Data\n");
523 if (pDecHandle->codecType == V4L2_PIX_FMT_H264) {
524 const gchar *pStr = NULL;
526 if ((pStr = gst_structure_get_string (pStructure, "alignment"))) {
527 if (strcmp (pStr, "au") == 0) {
528 pDecHandle->h264Alignment = H264_PARSE_ALIGN_AU;
529 GST_DEBUG_OBJECT (pNxVideoDec, ">>>>> H264 alignment: au Type.");
530 } else if (strcmp (pStr, "nal") == 0) {
531 pDecHandle->h264Alignment = H264_PARSE_ALIGN_NAL;
532 GST_DEBUG_OBJECT (pNxVideoDec, ">>>>> H264 alignment: nal Type.");
534 GST_DEBUG_OBJECT (pNxVideoDec, "unknown alignment: %s", pStr);
540 gst_video_decoder_set_output_state (pDecoder, GST_VIDEO_FORMAT_S420,
541 pDecHandle->width, pDecHandle->height, pNxVideoDec->pInputState);
543 pOutputState->caps = gst_caps_new_simple ("video/x-raw",
544 "format", G_TYPE_STRING,
545 gst_video_format_to_string (GST_VIDEO_FORMAT_S420), "width", G_TYPE_INT,
546 pDecHandle->width, "height", G_TYPE_INT, pDecHandle->height, "framerate",
547 GST_TYPE_FRACTION, pDecHandle->fpsNum, pDecHandle->fpsDen, NULL);
549 gst_video_codec_state_unref (pOutputState);
551 pNxVideoDec->pNxVideoDecHandle->imgPlaneNum = 1;
552 #if SUPPORT_NO_MEMORY_COPY
553 GST_DEBUG_OBJECT (pNxVideoDec, ">>>>> Accelerable.");
555 if (BUFFER_TYPE_GEM == pNxVideoDec->bufferType) {
556 GST_DEBUG_OBJECT (pNxVideoDec, ">>>>> Accelerable.");
560 ret = gst_video_decoder_negotiate (pDecoder);
563 GST_ERROR ("Fail Negotiate !\n");
567 #ifdef TIZEN_FEATURE_ARTIK530
568 if (!bIsFormatChange) {
573 if (pDecHandle->hCodec) {
574 NX_V4l2DecClose (pDecHandle->hCodec);
575 pDecHandle->hCodec = NULL;
577 if (pDecHandle->pTmpStrmBuf) {
578 g_free (pDecHandle->pTmpStrmBuf);
579 pDecHandle->pTmpStrmBuf = NULL;
582 pDecHandle->bInitialized = FALSE;
586 if (0 != InitVideoDec (pNxVideoDec->pNxVideoDecHandle)) {
596 gst_nxvideodec_flush (GstVideoDecoder * pDecoder)
598 GstNxVideoDec *pNxvideodec = GST_NXVIDEODEC (pDecoder);
602 GST_DEBUG_OBJECT (pNxvideodec, "flush");
604 if (pNxvideodec->pNxVideoDecHandle) {
605 pNxvideodec->pNxVideoDecHandle->bFlush = TRUE;
613 #if SUPPORT_NO_MEMORY_COPY
615 nxvideodec_get_offset_stride (gint width, gint height, guint8 * pSrc,
616 gsize * pOffset, gint * pStride)
626 luStride = ALIGN (width, 32);
627 luVStride = ALIGN (height, 16);
628 cStride = luStride / 2;
629 cVStride = ALIGN (height / 2, 16);
631 pcb = plu + luStride * luVStride;
632 pcr = pcb + cStride * cVStride;
635 pOffset[1] = pcb - plu;
636 pOffset[2] = pcr - plu;
638 pStride[0] = luStride;
639 pStride[1] = cStride;
640 pStride[2] = cStride;
644 gst_nxvideodec_handle_frame (GstVideoDecoder * pDecoder,
645 GstVideoCodecFrame * pFrame)
647 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
648 NX_V4L2DEC_OUT decOut;
649 gint64 timeStamp = 0;
652 gboolean bKeyFrame = FALSE;
654 GstMemory *pGstmem = NULL;
655 GstBuffer *pGstbuf = NULL;
656 struct video_meta_mmap_buffer *pMeta = NULL;
658 NX_VID_MEMORY_INFO *pImg = NULL;
659 GstVideoCodecState *pState = NULL;
661 unsigned char *pVadd = NULL;
662 GstVideoMeta *pVmeta = NULL;
663 gint videoImgSize = 0;
666 gsize offset[3] = { 0, };
667 gint stride[3] = { 0, };
669 GstMemory *pMemMMVideoData = NULL;
673 if (!gst_buffer_map (pFrame->input_buffer, &mapInfo, GST_MAP_READ)) {
674 GST_ERROR ("Cannot map input buffer!");
675 gst_video_codec_frame_unref (pFrame);
676 return GST_FLOW_ERROR;
679 bKeyFrame = GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (pFrame);
682 VideoDecodeFrame (pNxVideoDec->pNxVideoDecHandle, pFrame->input_buffer,
685 gst_buffer_unmap (pFrame->input_buffer, &mapInfo);
686 if (DEC_ERR == ret) {
687 GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp);
688 return gst_video_decoder_drop_frame (pDecoder, pFrame);
689 } else if (DEC_INIT_ERR == ret) {
690 return GST_FLOW_ERROR;
693 if (decOut.dispIdx < 0) {
697 GST_DEBUG_OBJECT (pNxVideoDec, " decOut.dispIdx: %d\n", decOut.dispIdx);
700 (struct video_meta_mmap_buffer *) g_malloc (sizeof (struct
701 video_meta_mmap_buffer));
704 GST_ERROR_OBJECT (pNxVideoDec, "failed to malloc for meta");
705 gst_video_codec_frame_unref (pFrame);
706 return GST_FLOW_ERROR;
710 pMeta->v4l2BufferIdx = decOut.dispIdx;
711 pVadd = pImg->pBuffer[0];
712 pMeta->pNxVideoDec = pNxVideoDec;
715 pNxVideoDec->pNxVideoDecHandle->width *
716 pNxVideoDec->pNxVideoDecHandle->height * 1.5;
718 pGstmem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
719 pVadd, videoImgSize, 0, videoImgSize, pMeta, nxvideodec_buffer_finalize);
722 GST_ERROR_OBJECT (pNxVideoDec,
723 "failed to gst_memory_new_wrapped for mmap buffer");
724 gst_video_codec_frame_unref (pFrame);
728 pGstbuf = gst_buffer_new ();
730 GST_ERROR_OBJECT (pNxVideoDec, "failed to gst_buffer_new");
731 gst_video_codec_frame_unref (pFrame);
734 gst_buffer_append_memory (pGstbuf, pGstmem);
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);
744 gst_buffer_add_video_meta_full (pGstbuf, GST_VIDEO_FRAME_FLAG_NONE,
745 GST_VIDEO_INFO_FORMAT (&pState->info),
746 GST_VIDEO_INFO_WIDTH (&pState->info),
747 GST_VIDEO_INFO_HEIGHT (&pState->info), n_planes, offset, stride);
749 GST_ERROR_OBJECT (pNxVideoDec, "failed to gst_buffer_add_video_meta_full");
750 gst_video_codec_state_unref (pState);
751 gst_video_codec_frame_unref (pFrame);
755 pMemMMVideoData = nxvideodec_mmvideobuf_copy (pNxVideoDec, &decOut);
756 if (!pMemMMVideoData) {
757 GST_ERROR ("failed to get zero copy data");
758 gst_video_codec_state_unref (pState);
759 gst_video_codec_frame_unref (pFrame);
762 gst_buffer_append_memory (pGstbuf, pMemMMVideoData);
764 gst_buffer_add_mmvideobuffer_meta (pGstbuf, 1);
766 pFrame->output_buffer = pGstbuf;
768 if (-1 == GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp)) {
769 GST_DEBUG_OBJECT (pNxVideoDec, "Cannot Found Time Stamp!!!");
771 pFrame->pts = timeStamp;
772 GST_BUFFER_PTS (pFrame->output_buffer) = timeStamp;
774 gst_video_codec_state_unref (pState);
776 ret = gst_video_decoder_finish_frame (pDecoder, pFrame);
790 nxvideodec_buffer_finalize (pMeta);
793 return GST_FLOW_ERROR;
797 gst_nxvideodec_handle_frame (GstVideoDecoder * pDecoder,
798 GstVideoCodecFrame * pFrame)
800 GstNxVideoDec *pNxVideoDec = GST_NXVIDEODEC (pDecoder);
801 NX_V4L2DEC_OUT decOut;
802 gint64 timeStamp = 0;
805 gboolean bKeyFrame = FALSE;
806 GstMemory *pGstmem = NULL;
807 GstBuffer *pGstbuf = NULL;
808 struct video_meta_mmap_buffer *pMeta = NULL;
809 GstMemory *pMemMMVideoData = NULL;
813 if (!gst_buffer_map (pFrame->input_buffer, &mapInfo, GST_MAP_READ)) {
814 GST_ERROR ("Cannot map input buffer!");
815 gst_video_codec_frame_unref (pFrame);
816 return GST_FLOW_ERROR;
819 bKeyFrame = GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (pFrame);
822 VideoDecodeFrame (pNxVideoDec->pNxVideoDecHandle, pFrame->input_buffer,
825 gst_buffer_unmap (pFrame->input_buffer, &mapInfo);
826 if (DEC_ERR == ret) {
827 GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp);
828 return gst_video_decoder_drop_frame (pDecoder, pFrame);
829 } else if (DEC_INIT_ERR == ret) {
830 return GST_FLOW_ERROR;
833 if (decOut.dispIdx < 0) {
837 GST_DEBUG_OBJECT (pNxVideoDec, " decOut.dispIdx: %d\n", decOut.dispIdx);
839 if (BUFFER_TYPE_GEM == pNxVideoDec->bufferType) {
840 pGstbuf = gst_buffer_new ();
842 GST_ERROR_OBJECT (pNxVideoDec, "failed to gst_buffer_new");
843 gst_video_codec_frame_unref (pFrame);
847 pMemMMVideoData = nxvideodec_mmvideobuf_copy (pNxVideoDec, &decOut);
848 if (!pMemMMVideoData) {
849 GST_ERROR ("failed to get zero copy data");
850 gst_video_codec_frame_unref (pFrame);
853 gst_buffer_append_memory (pGstbuf, pMemMMVideoData);
856 (struct video_meta_mmap_buffer *) g_malloc (sizeof (struct
857 video_meta_mmap_buffer));
859 GST_ERROR_OBJECT (pNxVideoDec, "failed to malloc for meta");
860 gst_video_codec_frame_unref (pFrame);
861 return GST_FLOW_ERROR;
863 pMeta->v4l2BufferIdx = decOut.dispIdx;
864 pMeta->pNxVideoDec = pNxVideoDec;
865 pGstmem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
867 sizeof (struct video_meta_mmap_buffer),
869 sizeof (struct video_meta_mmap_buffer),
870 pMeta, nxvideodec_buffer_finalize);
872 GST_ERROR_OBJECT (pNxVideoDec,
873 "failed to gst_memory_new_wrapped for mmap buffer");
874 gst_video_codec_frame_unref (pFrame);
877 gst_buffer_append_memory (pGstbuf, pGstmem);
879 gst_buffer_add_mmvideobuffer_meta (pGstbuf, 0);
881 pFrame->output_buffer = pGstbuf;
883 if (-1 == GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp)) {
884 GST_DEBUG_OBJECT (pNxVideoDec, "Cannot Found Time Stamp!!!");
886 pFrame->pts = timeStamp;
887 GST_BUFFER_PTS (pFrame->output_buffer) = timeStamp;
889 GstVideoFrame videoFrame;
890 NX_VID_MEMORY_INFO *pImg = NULL;
891 guint8 *pPtr = NULL;;
892 GstVideoCodecState *pState = NULL;
893 GstFlowReturn flowRet;
902 flowRet = gst_video_decoder_allocate_output_frame (pDecoder, pFrame);
903 pState = gst_video_decoder_get_output_state (pDecoder);
904 if (flowRet != GST_FLOW_OK) {
905 gst_video_codec_state_unref (pState);
906 gst_video_codec_frame_unref (pFrame);
910 if (!gst_video_frame_map (&videoFrame, &pState->info, pFrame->output_buffer,
912 GST_ERROR ("Cannot video frame map!\n");
913 gst_video_codec_state_unref (pState);
914 gst_video_codec_frame_unref (pFrame);
915 return GST_FLOW_ERROR;
918 if (-1 == GetTimeStamp (pNxVideoDec->pNxVideoDecHandle, &timeStamp)) {
919 GST_DEBUG_OBJECT (pNxVideoDec, "Cannot Found Time Stamp!!!");
921 pFrame->pts = timeStamp;
922 GST_BUFFER_PTS (pFrame->output_buffer) = timeStamp;
925 pPtr = GST_VIDEO_FRAME_COMP_DATA (&videoFrame, 0);
927 luStride = ALIGN (pNxVideoDec->pNxVideoDecHandle->width, 32);
928 luVStride = ALIGN (pNxVideoDec->pNxVideoDecHandle->height, 16);
929 cStride = luStride / 2;
930 cVStride = ALIGN (pNxVideoDec->pNxVideoDecHandle->height / 2, 16);
931 plu = (guint8 *) pImg->pBuffer[0];
932 pcb = plu + luStride * luVStride;
933 pcr = pcb + cStride * cVStride;
935 CopyImageToBufferYV12 ((guint8 *) plu, (guint8 *) pcb, (guint8 *) pcr,
936 pPtr, luStride, cStride, pNxVideoDec->pNxVideoDecHandle->width,
937 pNxVideoDec->pNxVideoDecHandle->height);
939 DisplayDone (pNxVideoDec->pNxVideoDecHandle, decOut.dispIdx);
941 gst_video_frame_unmap (&videoFrame);
942 gst_video_codec_state_unref (pState);
945 ret = gst_video_decoder_finish_frame (pDecoder, pFrame);
956 nxvideodec_buffer_finalize (pMeta);
959 return GST_FLOW_ERROR;
964 nxvideodec_buffer_finalize (gpointer pData)
970 struct video_meta_mmap_buffer *pMeta =
971 (struct video_meta_mmap_buffer *) pData;
974 GST_ERROR ("Error: pData is null !");
978 if ((pMeta->pNxVideoDec) && (pMeta->pNxVideoDec->pNxVideoDecHandle)) {
979 pthread_mutex_lock (&pMeta->pNxVideoDec->mutex);
980 if (PLAY == pMeta->pNxVideoDec->isState) {
981 GST_DEBUG_OBJECT (pMeta->pNxVideoDec, "v4l2BufferIdx: %d\n",
982 pMeta->v4l2BufferIdx);
984 DisplayDone (pMeta->pNxVideoDec->pNxVideoDecHandle,
985 pMeta->v4l2BufferIdx);
987 GST_ERROR ("Fail: DisplayDone !");
990 pthread_mutex_unlock (&pMeta->pNxVideoDec->mutex);
992 GST_ERROR ("Error: hCodec is null !");
1001 nxvideodec_mmvideobuf_copy (GstNxVideoDec *pNxVideoDec, NX_V4L2DEC_OUT * pDecOut)
1003 GstMemory *pMeta = NULL;
1004 MMVideoBuffer *pMMVideoBuf = NULL;
1006 pMMVideoBuf = (MMVideoBuffer *) g_malloc (sizeof (MMVideoBuffer));
1008 GST_ERROR ("failed to alloc MMVideoBuffer");
1012 memset ((void *) pMMVideoBuf, 0, sizeof (MMVideoBuffer));
1014 if (1 == pDecOut->hImg.planes) {
1015 pMMVideoBuf->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
1016 pMMVideoBuf->plane_num = 3;
1017 pMMVideoBuf->width[0] = pDecOut->hImg.width;
1018 pMMVideoBuf->height[0] = pDecOut->hImg.height;
1019 pMMVideoBuf->stride_width[0] = GST_ROUND_UP_32 (pDecOut->hImg.width);
1020 pMMVideoBuf->stride_width[1] = pMMVideoBuf->stride_width[0] >> 1;
1021 pMMVideoBuf->stride_width[2] = pMMVideoBuf->stride_width[1];
1022 pMMVideoBuf->stride_height[0] = GST_ROUND_UP_16 (pDecOut->hImg.height);
1023 pMMVideoBuf->stride_height[1] = GST_ROUND_UP_16 (pDecOut->hImg.height >> 1);
1024 pMMVideoBuf->stride_height[2] = pMMVideoBuf->stride_height[1];
1025 pMMVideoBuf->size[0] = pMMVideoBuf->stride_width[0] * pMMVideoBuf->stride_height[0];;
1026 pMMVideoBuf->size[1] = pMMVideoBuf->stride_width[1] * pMMVideoBuf->stride_height[1];
1027 pMMVideoBuf->size[2] = pMMVideoBuf->stride_width[2] * pMMVideoBuf->stride_height[2];
1028 pMMVideoBuf->data[0] = pDecOut->hImg.pBuffer[0];
1029 pMMVideoBuf->data[1] = pDecOut->hImg.pBuffer[0] + pMMVideoBuf->size[0];
1030 pMMVideoBuf->data[2] = pMMVideoBuf->data[1] + pMMVideoBuf->size[1];
1031 pMMVideoBuf->handle_num = 1;
1032 pMMVideoBuf->handle_size[0] = pMMVideoBuf->stride_width[0] * pMMVideoBuf->stride_height[0];
1033 pMMVideoBuf->handle_size[1] = pMMVideoBuf->stride_width[1] * pMMVideoBuf->stride_height[1];
1034 pMMVideoBuf->handle_size[2] = pMMVideoBuf->stride_width[2] * pMMVideoBuf->stride_height[2];
1035 #ifdef TIZEN_FEATURE_ARTIK530
1036 pMMVideoBuf->handle.bo[0] = pDecOut->hImg.bo[0];
1037 if (!pMMVideoBuf->handle.bo[0])
1038 GST_ERROR ("bo = null\n");
1040 } else if (3 == pDecOut->hImg.planes) {
1041 pMMVideoBuf->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
1042 pMMVideoBuf->format = MM_PIXEL_FORMAT_I420;
1043 pMMVideoBuf->plane_num = 3;
1044 pMMVideoBuf->width[0] = pDecOut->hImg.width;
1045 pMMVideoBuf->height[0] = pDecOut->hImg.height;
1046 pMMVideoBuf->stride_width[0] = pDecOut->hImg.stride[0];
1047 pMMVideoBuf->stride_width[1] = pDecOut->hImg.stride[1];
1048 pMMVideoBuf->stride_width[2] = pDecOut->hImg.stride[2];
1049 pMMVideoBuf->size[0] = pDecOut->hImg.size[0];
1050 pMMVideoBuf->size[1] = pDecOut->hImg.size[1];
1051 pMMVideoBuf->size[2] = pDecOut->hImg.size[2];
1052 pMMVideoBuf->data[0] = pDecOut->hImg.pBuffer[0];
1053 pMMVideoBuf->data[1] = pDecOut->hImg.pBuffer[1];
1054 pMMVideoBuf->data[2] = pDecOut->hImg.pBuffer[2];
1055 pMMVideoBuf->handle_num = 3;
1056 #ifdef TIZEN_FEATURE_ARTIK530
1057 pMMVideoBuf->handle.bo[0] = pDecOut->hImg.bo[0];
1058 pMMVideoBuf->handle.bo[1] = pDecOut->hImg.bo[1];
1059 pMMVideoBuf->handle.bo[2] = pDecOut->hImg.bo[2];
1060 if (!pMMVideoBuf->handle.bo[0])
1061 GST_ERROR ("bo[0] = null\n");
1062 if (!pMMVideoBuf->handle.bo[1])
1063 GST_ERROR ("bo[1] = null\n");
1064 if (!pMMVideoBuf->handle.bo[2])
1065 GST_ERROR ("bo[2] = null\n");
1068 #ifdef CODEC_DEC_OUTPUT_DUMP /* for decoder output dump */
1069 decoder_output_dump (pMMVideoBuf);
1071 pMeta = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
1073 sizeof (MMVideoBuffer), 0, sizeof (MMVideoBuffer), pMMVideoBuf, g_free);
1079 plugin_init (GstPlugin * plugin)
1085 /* FIXME Remember to set the rank if it's an element that is meant
1086 to be autoplugged by decodebin. */
1087 ret = gst_element_register (plugin, "nxvideodec", GST_RANK_PRIMARY + 1,
1088 GST_TYPE_NXVIDEODEC);
1095 #define VERSION "0.1.0"
1098 #define PACKAGE "S5P6818 GStreamer PlugIn"
1100 #ifndef PACKAGE_NAME
1101 #define PACKAGE_NAME "S5P6818 GStreamer PlugIn"
1103 #ifndef GST_PACKAGE_ORIGIN
1104 #define GST_PACKAGE_ORIGIN "http://www.nexell.co.kr"
1107 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1110 "Nexell H/W Video Decoder for S5P6818",
1111 plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN)