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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, 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 
GstMpeg2EncStreamWriter(GstPad * in_pad,EncoderParams * params)37 GstMpeg2EncStreamWriter::GstMpeg2EncStreamWriter (GstPad * in_pad,
38     EncoderParams * params)
39 {
40   pad = in_pad;
41   gst_object_ref (pad);
42   buf = NULL;
43 }
44 
~GstMpeg2EncStreamWriter()45 GstMpeg2EncStreamWriter::~GstMpeg2EncStreamWriter ()
46 {
47   gst_object_unref (pad);
48 }
49 
50 void
WriteOutBufferUpto(const guint8 * buffer,const guint32 flush_upto)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   gst_buffer_fill (buf, 0, buffer, flush_upto);
59   flushed += flush_upto;
60 
61   /* this should not block anything else (e.g. chain), but if it does,
62    * it's ok as mpeg2enc is not really a loop-based element, but push-based */
63   GST_MPEG2ENC_MUTEX_LOCK (enc);
64   /* best effort at giving output some meaningful time metadata
65    * no mpeg2enc specs on this though, but it might help getting the output
66    * into container formats that really do like timestamps (unlike mplex) */
67   if ((inbuf = (GstBuffer *) g_queue_pop_head (enc->time))) {
68     GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_TIMESTAMP (inbuf);
69     GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (inbuf);
70     gst_buffer_unref (inbuf);
71   }
72   enc->srcresult = gst_pad_push (pad, buf);
73   GST_MPEG2ENC_MUTEX_UNLOCK (enc);
74 }
75 
76 guint64
BitCount()77 GstMpeg2EncStreamWriter::BitCount ()
78 {
79   return flushed * 8ll;
80 }
81 
82 #else
83 
84 #define BUFSIZE (128*1024)
85 
86 /*
87  * Class init stuff.
88  */
89 
GstMpeg2EncStreamWriter(GstPad * in_pad,EncoderParams * params)90 GstMpeg2EncStreamWriter::GstMpeg2EncStreamWriter (GstPad * in_pad, EncoderParams * params):
91 ElemStrmWriter (*params)
92 {
93   pad = in_pad;
94   gst_object_ref (pad);
95   buf = NULL;
96 }
97 
~GstMpeg2EncStreamWriter()98 GstMpeg2EncStreamWriter::~GstMpeg2EncStreamWriter ()
99 {
100   gst_object_unref (pad);
101 }
102 
103 /*
104  * Output functions.
105  */
106 
107 void
PutBits(guint32 val,gint n)108 GstMpeg2EncStreamWriter::PutBits (guint32 val, gint n)
109 {
110   /* only relevant bits. Note that (according to Andrew),
111    * some CPUs do bitshifts modulo wordsize (32), which
112    * means that we have to check for n != 32 before
113    * bitshifting to the relevant bits (i.e. 0xffffffff <<
114    * 32 == 0xffffffff). */
115   if (n != 32)
116     val &= ~(0xffffffffU << n);
117 
118   /* write data */
119   while (n >= outcnt) {
120     if (!buf) {
121       buf = gst_buffer_new_and_alloc (BUFSIZE);
122       GST_BUFFER_SIZE (buf) = 0;
123     }
124 
125     outbfr = (outbfr << outcnt) | (val >> (n - outcnt));
126     GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf)++] = outbfr;
127     n -= outcnt;
128     outcnt = 8;
129     bytecnt++;
130 
131     if (GST_BUFFER_SIZE (buf) >= BUFSIZE)
132       FrameFlush ();
133   }
134 
135   /* cache remaining bits */
136   if (n != 0) {
137     outbfr = (outbfr << n) | val;
138     outcnt -= n;
139   }
140 }
141 
142 void
FrameBegin()143 GstMpeg2EncStreamWriter::FrameBegin ()
144 {
145 }
146 
147 void
FrameFlush()148 GstMpeg2EncStreamWriter::FrameFlush ()
149 {
150   GstMpeg2enc *enc = GST_MPEG2ENC (GST_PAD_PARENT (pad));
151 
152   if (buf) {
153     /* this should not block anything else (e.g. chain), but if it does,
154      * it's ok as mpeg2enc is not really a loop-based element, but push-based */
155     GST_MPEG2ENC_MUTEX_LOCK (enc);
156     gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
157     enc->srcresult = gst_pad_push (pad, buf);
158     GST_MPEG2ENC_MUTEX_UNLOCK (enc);
159     buf = NULL;
160   }
161 }
162 
163 void
FrameDiscard()164 GstMpeg2EncStreamWriter::FrameDiscard ()
165 {
166 }
167 #endif /* GST_MJPEGTOOLS_API >= 10800 */
168