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