From b0013f127eedd74bf7f625e1f52dba13ce77a741 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Fri, 9 Mar 2018 15:32:52 +0100 Subject: WIP more qtmux CC --- gst/isomp4/gstqtmux.c | 121 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 85 insertions(+), 36 deletions(-) diff --git a/gst/isomp4/gstqtmux.c b/gst/isomp4/gstqtmux.c index 81eee0d9b..bab212654 100644 --- a/gst/isomp4/gstqtmux.c +++ b/gst/isomp4/gstqtmux.c @@ -919,10 +919,13 @@ gst_qt_mux_prepare_caption_buffer (GstQTPad * qtpad, GstBuffer * buf, GstBuffer *newbuf = NULL; GstMapInfo map, inmap; gsize size; + gboolean in_prefill; if (buf == NULL) return NULL; + in_prefill = (qtmux->mux_mode == GST_QT_MUX_MODE_ROBUST_RECORDING_PREFILL); + size = gst_buffer_get_size (buf); gst_buffer_map (buf, &inmap, GST_MAP_READ); @@ -951,23 +954,39 @@ gst_qt_mux_prepare_caption_buffer (GstQTPad * qtpad, GstBuffer * buf, break; } - newbuf = gst_buffer_new_and_alloc (total_size); + newbuf = gst_buffer_new_and_alloc (in_prefill ? 20 : total_size); /* Let's copy over all metadata and not the memory */ gst_buffer_copy_into (newbuf, buf, GST_BUFFER_COPY_METADATA, 0, size); gst_buffer_map (newbuf, &map, GST_MAP_WRITE); - if (cdat_size) { - GST_WRITE_UINT32_BE (map.data, cdat_size + 8); + if (cdat_size || in_prefill) { + GST_WRITE_UINT32_BE (map.data, in_prefill ? 10 : cdat_size + 8); GST_WRITE_UINT32_LE (map.data + 4, FOURCC_cdat); - memcpy (map.data + 8, cdat, cdat_size); - write_offs = cdat_size + 8; - g_free (cdat); + if (cdat_size) + memcpy (map.data + 8, cdat, in_prefill ? 2 : cdat_size); + else { + /* Write 'empty' CC */ + map.data[8] = 0x80; + map.data[9] = 0x80; + } + write_offs = in_prefill ? 10 : cdat_size + 8; + if (cdat_size) + g_free (cdat); } - if (cdt2_size) { - GST_WRITE_UINT32_BE (map.data + write_offs, cdt2_size + 8); + + if (cdt2_size || in_prefill) { + GST_WRITE_UINT32_BE (map.data + write_offs, + in_prefill ? 10 : cdt2_size + 8); GST_WRITE_UINT32_LE (map.data + write_offs + 4, FOURCC_cdt2); - memcpy (map.data + write_offs + 8, cdt2, cdt2_size); - g_free (cdt2); + if (cdt2_size) + memcpy (map.data + write_offs + 8, cdt2, in_prefill ? 2 : cdt2_size); + else { + /* Write 'empty' CC */ + map.data[write_offs + 8] = 0x80; + map.data[write_offs + 9] = 0x80; + } + if (cdt2_size) + g_free (cdt2); } gst_buffer_unmap (newbuf, &map); break; @@ -976,7 +995,11 @@ gst_qt_mux_prepare_caption_buffer (GstQTPad * qtpad, GstBuffer * buf, case FOURCC_c708: { /* Take the whole CDP */ - newbuf = gst_buffer_new_and_alloc (size + 8); + if (in_prefill && size > 92) { + GST_ERROR_OBJECT (qtmux, "Input C708 CDP too big for prefill mode !"); + break; + } + newbuf = gst_buffer_new_and_alloc (in_prefill ? 100 : size + 8); /* Let's copy over all metadata and not the memory */ gst_buffer_copy_into (newbuf, buf, GST_BUFFER_COPY_METADATA, 0, size); @@ -2402,6 +2425,8 @@ prefill_get_block_index (GstQTMux * qtmux, GstQTPad * qpad) case FOURCC_apco: case FOURCC_ap4h: case FOURCC_ap4x: + case FOURCC_c608: + case FOURCC_c708: return qpad->sample_offset; case FOURCC_sowt: case FOURCC_twos: @@ -2470,6 +2495,12 @@ prefill_get_sample_size (GstQTMux * qtmux, GstQTPad * qpad) return 900000; } break; + case FOURCC_c608: + /* We always write both cdat and cdt2 atom in prefill mode */ + return 20; + case FOURCC_c708: + /* We're cheating a bit by always allocating 100bytes even if we use less */ + return 100; case FOURCC_sowt: case FOURCC_twos:{ guint64 block_idx; @@ -2504,6 +2535,8 @@ prefill_get_next_timestamp (GstQTMux * qtmux, GstQTPad * qpad) case FOURCC_apco: case FOURCC_ap4h: case FOURCC_ap4x: + case FOURCC_c608: + case FOURCC_c708: return gst_util_uint64_scale (qpad->sample_offset + 1, qpad->expected_sample_duration_d * GST_SECOND, qpad->expected_sample_duration_n); @@ -2600,6 +2633,33 @@ prefill_raw_audio_prepare_buf_func (GstQTPad * qtpad, GstBuffer * buf, return buf; } +static void +find_video_sample_duration (GstQTMux * qtmux, guint * dur_n, guint * dur_d) +{ + GSList *walk; + + /* Find the (first) video track and assume that we have to output + * in that size */ + for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) { + GstCollectData *cdata = (GstCollectData *) walk->data; + GstQTPad *tmp_qpad = (GstQTPad *) cdata; + + if (tmp_qpad->trak->is_video) { + *dur_n = tmp_qpad->expected_sample_duration_n; + *dur_d = tmp_qpad->expected_sample_duration_d; + break; + } + } + + if (walk == NULL) { + GST_INFO_OBJECT (qtmux, + "Found no video framerate, using 40ms audio buffers"); + *dur_n = 25; + *dur_d = 1; + } +} + +/* Called when all pads are prerolled to adjust and */ static gboolean prefill_update_sample_size (GstQTMux * qtmux, GstQTPad * qpad) { @@ -2609,37 +2669,26 @@ prefill_update_sample_size (GstQTMux * qtmux, GstQTPad * qpad) case FOURCC_apcs: case FOURCC_apco: case FOURCC_ap4h: - case FOURCC_ap4x:{ + case FOURCC_ap4x: + { + guint sample_size = prefill_get_sample_size (qtmux, qpad); + atom_trak_set_constant_size_samples (qpad->trak, sample_size); + return TRUE; + } + case FOURCC_c608: + case FOURCC_c708: + { guint sample_size = prefill_get_sample_size (qtmux, qpad); + /* We need a "valid" duration */ + find_video_sample_duration (qtmux, &qpad->expected_sample_duration_n, + &qpad->expected_sample_duration_d); atom_trak_set_constant_size_samples (qpad->trak, sample_size); return TRUE; } case FOURCC_sowt: case FOURCC_twos:{ - GSList *walk; - - /* Find the (first) video track and assume that we have to output - * in that size */ - for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) { - GstCollectData *cdata = (GstCollectData *) walk->data; - GstQTPad *tmp_qpad = (GstQTPad *) cdata; - - if (tmp_qpad->trak->is_video) { - qpad->expected_sample_duration_n = - tmp_qpad->expected_sample_duration_n; - qpad->expected_sample_duration_d = - tmp_qpad->expected_sample_duration_d; - break; - } - } - - if (walk == NULL) { - GST_INFO_OBJECT (qpad->collect.pad, - "Found no video framerate, using 40ms audio buffers"); - qpad->expected_sample_duration_n = 25; - qpad->expected_sample_duration_d = 1; - } - + find_video_sample_duration (qtmux, &qpad->expected_sample_duration_n, + &qpad->expected_sample_duration_d); /* Set a prepare_buf_func that ensures this */ qpad->prepare_buf_func = prefill_raw_audio_prepare_buf_func; qpad->raw_audio_adapter = gst_adapter_new (); -- cgit v1.2.3