Tizen 2.0 Release
[framework/multimedia/gst-plugins-bad0.10.git] / ext / mpeg2enc / gstmpeg2encstreamwriter.cc
1 /* GStreamer mpeg2enc (mjpegtools) wrapper
2  * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  * (c) 2006 Mark Nauwelaerts <manauw@skynet.be>
4  *
5  * gstmpeg2encstreamwriter.cc: GStreamer/mpeg2enc output wrapper
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "gstmpeg2enc.hh"
28 #include "gstmpeg2encstreamwriter.hh"
29 #include <string.h>
30
31 #if GST_MJPEGTOOLS_API >= 10800
32
33 /*
34  * Class init stuff.
35  */
36
37 GstMpeg2EncStreamWriter::GstMpeg2EncStreamWriter (GstPad * in_pad,
38     EncoderParams * params)
39 {
40   pad = in_pad;
41   gst_object_ref (pad);
42   buf = NULL;
43 }
44
45 GstMpeg2EncStreamWriter::~GstMpeg2EncStreamWriter ()
46 {
47   gst_object_unref (pad);
48 }
49
50 void
51 GstMpeg2EncStreamWriter::WriteOutBufferUpto (const guint8 * buffer,
52     const guint32 flush_upto)
53 {
54   GstBuffer *buf, *inbuf;
55   GstMpeg2enc *enc = GST_MPEG2ENC (GST_PAD_PARENT (pad));
56
57   buf = gst_buffer_new_and_alloc (flush_upto);
58
59   memcpy (GST_BUFFER_DATA (buf), buffer, flush_upto);
60   flushed += flush_upto;
61
62   /* this should not block anything else (e.g. chain), but if it does,
63    * it's ok as mpeg2enc is not really a loop-based element, but push-based */
64   GST_MPEG2ENC_MUTEX_LOCK (enc);
65   /* best effort at giving output some meaningful time metadata
66    * no mpeg2enc specs on this though, but it might help getting the output
67    * into container formats that really do like timestamps (unlike mplex) */
68   if ((inbuf = (GstBuffer *) g_queue_pop_head (enc->time))) {
69     GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_TIMESTAMP (inbuf);
70     GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (inbuf);
71     gst_buffer_unref (inbuf);
72   }
73   gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
74   enc->srcresult = gst_pad_push (pad, buf);
75   GST_MPEG2ENC_MUTEX_UNLOCK (enc);
76 }
77
78 guint64
79 GstMpeg2EncStreamWriter::BitCount ()
80 {
81   return flushed * 8ll;
82 }
83
84 #else
85
86 #define BUFSIZE (128*1024)
87
88 /*
89  * Class init stuff.
90  */
91
92 GstMpeg2EncStreamWriter::GstMpeg2EncStreamWriter (GstPad * in_pad, EncoderParams * params):
93 ElemStrmWriter (*params)
94 {
95   pad = in_pad;
96   gst_object_ref (pad);
97   buf = NULL;
98 }
99
100 GstMpeg2EncStreamWriter::~GstMpeg2EncStreamWriter ()
101 {
102   gst_object_unref (pad);
103 }
104
105 /*
106  * Output functions.
107  */
108
109 void
110 GstMpeg2EncStreamWriter::PutBits (guint32 val, gint n)
111 {
112   /* only relevant bits. Note that (according to Andrew),
113    * some CPUs do bitshifts modulo wordsize (32), which
114    * means that we have to check for n != 32 before
115    * bitshifting to the relevant bits (i.e. 0xffffffff <<
116    * 32 == 0xffffffff). */
117   if (n != 32)
118     val &= ~(0xffffffffU << n);
119
120   /* write data */
121   while (n >= outcnt) {
122     if (!buf) {
123       buf = gst_buffer_new_and_alloc (BUFSIZE);
124       GST_BUFFER_SIZE (buf) = 0;
125     }
126
127     outbfr = (outbfr << outcnt) | (val >> (n - outcnt));
128     GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf)++] = outbfr;
129     n -= outcnt;
130     outcnt = 8;
131     bytecnt++;
132
133     if (GST_BUFFER_SIZE (buf) >= BUFSIZE)
134       FrameFlush ();
135   }
136
137   /* cache remaining bits */
138   if (n != 0) {
139     outbfr = (outbfr << n) | val;
140     outcnt -= n;
141   }
142 }
143
144 void
145 GstMpeg2EncStreamWriter::FrameBegin ()
146 {
147 }
148
149 void
150 GstMpeg2EncStreamWriter::FrameFlush ()
151 {
152   GstMpeg2enc *enc = GST_MPEG2ENC (GST_PAD_PARENT (pad));
153
154   if (buf) {
155     /* this should not block anything else (e.g. chain), but if it does,
156      * it's ok as mpeg2enc is not really a loop-based element, but push-based */
157     GST_MPEG2ENC_MUTEX_LOCK (enc);
158     gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
159     enc->srcresult = gst_pad_push (pad, buf);
160     GST_MPEG2ENC_MUTEX_UNLOCK (enc);
161     buf = NULL;
162   }
163 }
164
165 void
166 GstMpeg2EncStreamWriter::FrameDiscard ()
167 {
168 }
169 #endif /* GST_MJPEGTOOLS_API >= 10800 */