1 /* GStreamer
2  * Copyright (C) 2008-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 /* Implementation of SMPTE 386M - Mapping Type-D10 essence data into the MXF
21  * Generic Container
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <gst/gst.h>
29 #include <gst/audio/audio.h>
30 #include <string.h>
31 
32 #include "mxfd10.h"
33 
34 #include "mxfmpeg.h"
35 #include "mxfessence.h"
36 
37 GST_DEBUG_CATEGORY_EXTERN (mxf_debug);
38 #define GST_CAT_DEFAULT mxf_debug
39 
40 typedef struct
41 {
42   guint width, channels;
43 } MXFD10AudioMappingData;
44 
45 static gboolean
mxf_is_d10_essence_track(const MXFMetadataTimelineTrack * track)46 mxf_is_d10_essence_track (const MXFMetadataTimelineTrack * track)
47 {
48   guint i;
49 
50   g_return_val_if_fail (track != NULL, FALSE);
51 
52   if (track->parent.descriptor == NULL)
53     return FALSE;
54 
55   for (i = 0; i < track->parent.n_descriptor; i++) {
56     MXFMetadataFileDescriptor *d = track->parent.descriptor[i];
57     MXFUL *key;
58 
59     if (!d)
60       continue;
61 
62     key = &d->essence_container;
63     /* SMPTE 386M 5.1 */
64     if (mxf_is_generic_container_essence_container_label (key) &&
65         key->u[12] == 0x02 && key->u[13] == 0x01 &&
66         (key->u[14] >= 0x01 && key->u[14] <= 0x06) &&
67         (key->u[15] == 0x01 || key->u[15] == 0x02))
68       return TRUE;
69   }
70 
71   return FALSE;
72 }
73 
74 static GstFlowReturn
mxf_d10_picture_handle_essence_element(const MXFUL * key,GstBuffer * buffer,GstCaps * caps,MXFMetadataTimelineTrack * track,gpointer mapping_data,GstBuffer ** outbuf)75 mxf_d10_picture_handle_essence_element (const MXFUL * key, GstBuffer * buffer,
76     GstCaps * caps,
77     MXFMetadataTimelineTrack * track,
78     gpointer mapping_data, GstBuffer ** outbuf)
79 {
80   *outbuf = buffer;
81 
82   /* SMPTE 386M 5.2.1 */
83   if (key->u[12] != 0x05 || key->u[13] != 0x01 || key->u[14] != 0x01) {
84     GST_ERROR ("Invalid D10 picture essence element");
85     return GST_FLOW_ERROR;
86   }
87 
88   if (mxf_mpeg_is_mpeg2_keyframe (buffer))
89     GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
90   else
91     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
92 
93   return GST_FLOW_OK;
94 }
95 
96 static GstFlowReturn
mxf_d10_sound_handle_essence_element(const MXFUL * key,GstBuffer * buffer,GstCaps * caps,MXFMetadataTimelineTrack * track,gpointer mapping_data,GstBuffer ** outbuf)97 mxf_d10_sound_handle_essence_element (const MXFUL * key, GstBuffer * buffer,
98     GstCaps * caps,
99     MXFMetadataTimelineTrack * track,
100     gpointer mapping_data, GstBuffer ** outbuf)
101 {
102   guint i, j, nsamples;
103   const guint8 *indata;
104   guint8 *outdata;
105   GstMapInfo map;
106   GstMapInfo outmap;
107   MXFD10AudioMappingData *data = mapping_data;
108 
109   g_return_val_if_fail (data != NULL, GST_FLOW_ERROR);
110   g_return_val_if_fail (data->channels != 0
111       && data->width != 0, GST_FLOW_ERROR);
112 
113   /* SMPTE 386M 5.3.1 */
114   if (key->u[12] != 0x06 || key->u[13] != 0x01 || key->u[14] != 0x10) {
115     GST_ERROR ("Invalid D10 sound essence element");
116     return GST_FLOW_ERROR;
117   }
118 
119   gst_buffer_map (buffer, &map, GST_MAP_READ);
120 
121   /* Now transform raw AES3 into raw audio, see SMPTE 331M */
122   if ((map.size - 4) % 32 != 0) {
123     gst_buffer_unmap (buffer, &map);
124     GST_ERROR ("Invalid D10 sound essence buffer size");
125     return GST_FLOW_ERROR;
126   }
127 
128   nsamples = ((map.size - 4) / 4) / 8;
129 
130   *outbuf = gst_buffer_new_and_alloc (nsamples * data->width * data->channels);
131   gst_buffer_copy_into (*outbuf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
132   gst_buffer_map (*outbuf, &outmap, GST_MAP_WRITE);
133 
134   indata = map.data;
135   outdata = outmap.data;
136 
137   /* Skip 32 bit header */
138   indata += 4;
139 
140   for (i = 0; i < nsamples; i++) {
141     for (j = 0; j < data->channels; j++) {
142       guint32 in = GST_READ_UINT32_LE (indata);
143 
144       /* Remove first 4 and last 4 bits as they only
145        * contain status data. Shift the 24 bit samples
146        * to the correct width afterwards. */
147       if (data->width == 2) {
148         in = (in >> 12) & 0xffff;
149         GST_WRITE_UINT16_LE (outdata, in);
150       } else if (data->width == 3) {
151         in = (in >> 4) & 0xffffff;
152         GST_WRITE_UINT24_LE (outdata, in);
153       }
154       indata += 4;
155       outdata += data->width;
156     }
157     /* There are always 8 channels but only the first
158      * ones contain valid data, skip the others */
159     indata += 4 * (8 - data->channels);
160   }
161 
162   gst_buffer_unmap (*outbuf, &outmap);
163   gst_buffer_unmap (buffer, &map);
164   gst_buffer_unref (buffer);
165 
166   return GST_FLOW_OK;
167 }
168 
169 static MXFEssenceWrapping
mxf_d10_get_track_wrapping(const MXFMetadataTimelineTrack * track)170 mxf_d10_get_track_wrapping (const MXFMetadataTimelineTrack * track)
171 {
172   return MXF_ESSENCE_WRAPPING_FRAME_WRAPPING;
173 }
174 
175 static GstCaps *
mxf_d10_create_caps(MXFMetadataTimelineTrack * track,GstTagList ** tags,gboolean * intra_only,MXFEssenceElementHandleFunc * handler,gpointer * mapping_data)176 mxf_d10_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags,
177     gboolean * intra_only, MXFEssenceElementHandleFunc * handler,
178     gpointer * mapping_data)
179 {
180   MXFMetadataGenericPictureEssenceDescriptor *p = NULL;
181   MXFMetadataGenericSoundEssenceDescriptor *s = NULL;
182   guint i;
183   GstCaps *caps = NULL;
184 
185   g_return_val_if_fail (track != NULL, NULL);
186 
187   if (track->parent.descriptor == NULL) {
188     GST_ERROR ("No descriptor found for this track");
189     return NULL;
190   }
191 
192   for (i = 0; i < track->parent.n_descriptor; i++) {
193     if (!track->parent.descriptor[i])
194       continue;
195 
196     if (MXF_IS_METADATA_GENERIC_PICTURE_ESSENCE_DESCRIPTOR (track->parent.
197             descriptor[i])) {
198       p = (MXFMetadataGenericPictureEssenceDescriptor *) track->
199           parent.descriptor[i];
200       break;
201     } else if (MXF_IS_METADATA_GENERIC_SOUND_ESSENCE_DESCRIPTOR (track->parent.
202             descriptor[i])) {
203       s = (MXFMetadataGenericSoundEssenceDescriptor *) track->
204           parent.descriptor[i];
205       break;
206     }
207   }
208 
209   if (!s && !p) {
210     GST_ERROR ("No descriptor found for this track");
211     return NULL;
212   }
213 
214   if (!*tags)
215     *tags = gst_tag_list_new_empty ();
216 
217   if (s) {
218     MXFD10AudioMappingData *data;
219     GstAudioFormat audio_format;
220 
221     if (s->channel_count == 0 ||
222         s->quantization_bits == 0 ||
223         s->audio_sampling_rate.n == 0 || s->audio_sampling_rate.d == 0) {
224       GST_ERROR ("Invalid descriptor");
225       return NULL;
226     }
227 
228     if (s->quantization_bits != 16 && s->quantization_bits != 24) {
229       GST_ERROR ("Invalid width %u", s->quantization_bits);
230       return NULL;
231     }
232 
233     /* FIXME: set channel layout */
234 
235     audio_format =
236         gst_audio_format_build_integer (s->quantization_bits != 8,
237         G_LITTLE_ENDIAN, s->quantization_bits, s->quantization_bits);
238     caps =
239         mxf_metadata_generic_sound_essence_descriptor_create_caps (s,
240         &audio_format);
241 
242     *handler = mxf_d10_sound_handle_essence_element;
243 
244     data = g_new0 (MXFD10AudioMappingData, 1);
245     data->width = s->quantization_bits / 8;
246     data->channels = s->channel_count;
247     *mapping_data = data;
248 
249     gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
250         "SMPTE D-10 Audio", NULL);
251 
252     *intra_only = TRUE;
253   } else if (p) {
254     caps =
255         gst_caps_new_simple ("video/mpeg", "systemstream", G_TYPE_BOOLEAN,
256         FALSE, "mpegversion", G_TYPE_INT, 2, NULL);
257     mxf_metadata_generic_picture_essence_descriptor_set_caps (p, caps);
258 
259     *handler = mxf_d10_picture_handle_essence_element;
260     gst_tag_list_add (*tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
261         "SMPTE D-10 Video", NULL);
262 
263     /* Does not allow temporal reordering */
264     *intra_only = TRUE;
265   }
266 
267   return caps;
268 }
269 
270 static const MXFEssenceElementHandler mxf_d10_essence_element_handler = {
271   mxf_is_d10_essence_track,
272   mxf_d10_get_track_wrapping,
273   mxf_d10_create_caps
274 };
275 
276 void
mxf_d10_init(void)277 mxf_d10_init (void)
278 {
279   mxf_essence_element_handler_register (&mxf_d10_essence_element_handler);
280 }
281