1 /* GStreamer JPEG 2000 Parser
2 *
3 * Copyright (C) <2016> Milos Seleceni
4 * @author Milos Seleceni <milos.seleceni@comprimato.com>
5 *
6 * Copyright (C) <2016-2017> Grok Image Compression Inc.
7 * @author Aaron Boxer <boxerab@gmail.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <stdio.h>
30 #include "mpegtsmux_jpeg2000.h"
31 #include <string.h>
32 #include <gst/audio/audio.h>
33 #include <gst/base/gstbytewriter.h>
34 #include <gst/gst.h>
35
36 #define GST_CAT_DEFAULT mpegtsmux_debug
37
38 GstBuffer *
mpegtsmux_prepare_jpeg2000(GstBuffer * buf,MpegTsPadData * data,MpegTsMux * mux)39 mpegtsmux_prepare_jpeg2000 (GstBuffer * buf, MpegTsPadData * data,
40 MpegTsMux * mux)
41 {
42 j2k_private_data *private_data = data->prepare_data;
43 GstByteWriter wr;
44 GstBuffer *out_buf = NULL;
45 guint8 *elsm_header = NULL;
46 const guint header_size = private_data->interlace ? 48 : 38;
47 GstClockTime seconds = buf->pts / GST_SECOND;
48 GstClockTime minutes = seconds / 60;
49 GstClockTime hours = minutes / 60;
50
51 /* interlaced not supported */
52 if (private_data->interlace) {
53 GST_ERROR_OBJECT (mux, "Interlaced not supported");
54 return NULL;
55 }
56
57 seconds = seconds % 60;
58 minutes = minutes % 60;
59 hours = hours % 24;
60
61 /* ??? Hack for missing frame number index in buffer offset */
62 /* guint8 frame_number = private_data->frame_number % 60; */
63 gst_byte_writer_init_with_size (&wr, header_size, FALSE);
64
65 /* Elementary stream header box 'elsm' == 0x656c736d */
66 gst_byte_writer_put_uint32_be (&wr, 0x656c736d);
67 /* Framerate box 'frat' == 0x66726174 */
68 gst_byte_writer_put_uint32_be (&wr, 0x66726174);
69 /* put framerate denominator */
70 gst_byte_writer_put_uint16_be (&wr, private_data->den);
71 /* put framerate numerator */
72 gst_byte_writer_put_uint16_be (&wr, private_data->num);
73 /* Maximum bitrate box 'brat' == 0x62726174 */
74 gst_byte_writer_put_uint32_be (&wr, 0x62726174);
75 /* put Maximum bitrate */
76 gst_byte_writer_put_uint32_be (&wr, private_data->max_bitrate);
77 /* put size of first codestream */
78 /* private_data->AUF[0] */
79 gst_byte_writer_put_uint32_be (&wr, gst_buffer_get_size (buf));
80
81 /* ToDo: the if block below is never called, because we do not support muxing J2K-over-mpeg-TS interlaced data
82 * If we ever do, then the code below will need to tested and perhaps modified
83 */
84 if (private_data->interlace) {
85 /* put size of second codestream */
86 gst_byte_writer_put_uint32_be (&wr, gst_buffer_get_size (buf));
87 /* Time Code Box 'fiel' == 0x6669656c */
88 gst_byte_writer_put_uint32_be (&wr, 0x6669656c);
89 /* put Fic */
90 gst_byte_writer_put_uint8 (&wr, private_data->Fic);
91 /* put Fio */
92 gst_byte_writer_put_uint8 (&wr, private_data->Fio);
93 }
94
95 /* Time Code Box 'tcod' == 0x74636f64 */
96 gst_byte_writer_put_uint32_be (&wr, 0x74636f64);
97
98 /* put HHMMSSFF */
99 gst_byte_writer_put_uint8 (&wr, (guint8) hours);
100 gst_byte_writer_put_uint8 (&wr, (guint8) minutes);
101 gst_byte_writer_put_uint8 (&wr, (guint8) seconds);
102 gst_byte_writer_put_uint8 (&wr, 0x0);
103 /* ??? Hack for missing frame number index in buffer offset */
104 /* private_data->frame_number++; */
105
106 /* Broadcast Color Box 'bcol' == 0x62636f6c */
107 gst_byte_writer_put_uint32_be (&wr, 0x62636f6c);
108 /* put color spec */
109 gst_byte_writer_put_uint8 (&wr, private_data->color_spec);
110 /* put reserved 8-bit */
111 gst_byte_writer_put_uint8 (&wr, 0xff);
112 /* Allocate ELSM header size only; gst_buffer_copy_into will add gst_buffer_get_size (buf) bytes to out_buf */
113 out_buf = gst_buffer_new_and_alloc (header_size);
114
115 /* Copy ELSM header */
116 elsm_header = gst_byte_writer_reset_and_get_data (&wr);
117 gst_buffer_fill (out_buf, 0, elsm_header, header_size);
118 g_free (elsm_header);
119 /* Copy complete frame */
120 gst_buffer_copy_into (out_buf, buf,
121 GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_TIMESTAMPS |
122 GST_BUFFER_COPY_MEMORY, 0, -1);
123 GST_DEBUG_OBJECT (mux, "Prepared J2K PES of size %d",
124 (int) gst_buffer_get_size (out_buf));
125
126 return out_buf;
127 }
128
129 void
mpegtsmux_free_jpeg2000(gpointer prepare_data)130 mpegtsmux_free_jpeg2000 (gpointer prepare_data)
131 {
132 /* Free prepare data memory object */
133 g_free (prepare_data);
134 }
135