History

avformat/dash: move reused API to common file and header file

move from dashenc, move DASHTmplId and dash_fill_tmpl_params to dash.c, they will be used by dash demuxer and dash muxer. v2 fixed: 1. rename common file from dashcomm.* to dash.* Suggested-by: Hendrik Leppkes <h.leppkes@gmail.com> v3 fixed: 1. rename header file pre defined 2. add ff_ prefix for the internal API Suggested-by: James Almer <jamrial@gmail.com>

Steven Liu committed 9 years ago

Commit 837580f1 parent 9d00fb94 files · +180 −127Browse files

Unified · Split

4 files
  1. libavformat/Makefile +1 −1
  2. libavformat/dash.c +136 −0
  3. libavformat/dash.h +39 −0
  4. libavformat/dashenc.c +4 −126
libavformat/Makefile+1−1
@@ -132,7 +132,7 @@ OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o · 131 unmodified lines
132132 OBJS-$(CONFIG_CRC_MUXER) += crcenc.o
133133 OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o
134134 OBJS-$(CONFIG_DATA_MUXER) += rawenc.o
135−OBJS-$(CONFIG_DASH_MUXER) += dashenc.o
135+OBJS-$(CONFIG_DASH_MUXER) += dash.o dashenc.o
136136 OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o
137137 OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o
138138 OBJS-$(CONFIG_DCSTR_DEMUXER) += dcstr.o
libavformat/dash.c+136−0
@@ -0,0 +1,136 @@
1+#include "config.h"
2+#if HAVE_UNISTD_H
3+#include <unistd.h>
4+#endif
5+
6+#include "libavutil/avassert.h"
7+#include "libavutil/avstring.h"
8+#include "libavutil/intreadwrite.h"
9+#include "libavutil/mathematics.h"
10+#include "libavutil/opt.h"
11+#include "libavutil/rational.h"
12+#include "libavutil/time_internal.h"
13+
14+#include "avc.h"
15+#include "avformat.h"
16+#include "avio_internal.h"
17+#include "internal.h"
18+#include "isom.h"
19+#include "os_support.h"
20+#include "url.h"
21+#include "dash.h"
22+
23+static DASHTmplId dash_read_tmpl_id(const char *identifier, char *format_tag,
24+ size_t format_tag_size, const char **ptr) {
25+ const char *next_ptr;
26+ DASHTmplId id_type = DASH_TMPL_ID_UNDEFINED;
27+
28+ if (av_strstart(identifier, "$$", &next_ptr)) {
29+ id_type = DASH_TMPL_ID_ESCAPE;
30+ *ptr = next_ptr;
31+ } else if (av_strstart(identifier, "$RepresentationID$", &next_ptr)) {
32+ id_type = DASH_TMPL_ID_REP_ID;
33+ // default to basic format, as $RepresentationID$ identifiers
34+ // are not allowed to have custom format-tags.
35+ av_strlcpy(format_tag, "%d", format_tag_size);
36+ *ptr = next_ptr;
37+ } else { // the following identifiers may have an explicit format_tag
38+ if (av_strstart(identifier, "$Number", &next_ptr))
39+ id_type = DASH_TMPL_ID_NUMBER;
40+ else if (av_strstart(identifier, "$Bandwidth", &next_ptr))
41+ id_type = DASH_TMPL_ID_BANDWIDTH;
42+ else if (av_strstart(identifier, "$Time", &next_ptr))
43+ id_type = DASH_TMPL_ID_TIME;
44+ else
45+ id_type = DASH_TMPL_ID_UNDEFINED;
46+
47+ // next parse the dash format-tag and generate a c-string format tag
48+ // (next_ptr now points at the first '%' at the beginning of the format-tag)
49+ if (id_type != DASH_TMPL_ID_UNDEFINED) {
50+ const char *number_format = (id_type == DASH_TMPL_ID_TIME) ? PRId64 : "d";
51+ if (next_ptr[0] == '$') { // no dash format-tag
52+ snprintf(format_tag, format_tag_size, "%%%s", number_format);
53+ *ptr = &next_ptr[1];
54+ } else {
55+ const char *width_ptr;
56+ // only tolerate single-digit width-field (i.e. up to 9-digit width)
57+ if (av_strstart(next_ptr, "%0", &width_ptr) &&
58+ av_isdigit(width_ptr[0]) &&
59+ av_strstart(&width_ptr[1], "d$", &next_ptr)) {
60+ // yes, we're using a format tag to build format_tag.
61+ snprintf(format_tag, format_tag_size, "%s%c%s", "%0", width_ptr[0], number_format);
62+ *ptr = next_ptr;
63+ } else {
64+ av_log(NULL, AV_LOG_WARNING, "Failed to parse format-tag beginning with %s. Expected either a "
65+ "closing '$' character or a format-string like '%%0[width]d', "
66+ "where width must be a single digit\n", next_ptr);
67+ id_type = DASH_TMPL_ID_UNDEFINED;
68+ }
69+ }
70+ }
71+ }
72+ return id_type;
73+}
74+
75+void ff_dash_fill_tmpl_params(char *dst, size_t buffer_size,
76+ const char *template, int rep_id,
77+ int number, int bit_rate,
78+ int64_t time) {
79+ int dst_pos = 0;
80+ const char *t_cur = template;
81+ while (dst_pos < buffer_size - 1 && *t_cur) {
82+ char format_tag[7]; // May be "%d", "%0Xd", or "%0Xlld" (for $Time$), where X is in [0-9]
83+ int n = 0;
84+ DASHTmplId id_type;
85+ const char *t_next = strchr(t_cur, '$'); // copy over everything up to the first '$' character
86+ if (t_next) {
87+ int num_copy_bytes = FFMIN(t_next - t_cur, buffer_size - dst_pos - 1);
88+ av_strlcpy(&dst[dst_pos], t_cur, num_copy_bytes + 1);
89+ // advance
90+ dst_pos += num_copy_bytes;
91+ t_cur = t_next;
92+ } else { // no more DASH identifiers to substitute - just copy the rest over and break
93+ av_strlcpy(&dst[dst_pos], t_cur, buffer_size - dst_pos);
94+ break;
95+ }
96+
97+ if (dst_pos >= buffer_size - 1 || !*t_cur)
98+ break;
99+
100+ // t_cur is now pointing to a '$' character
101+ id_type = dash_read_tmpl_id(t_cur, format_tag, sizeof(format_tag), &t_next);
102+ switch (id_type) {
103+ case DASH_TMPL_ID_ESCAPE:
104+ av_strlcpy(&dst[dst_pos], "$", 2);
105+ n = 1;
106+ break;
107+ case DASH_TMPL_ID_REP_ID:
108+ n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, rep_id);
109+ break;
110+ case DASH_TMPL_ID_NUMBER:
111+ n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, number);
112+ break;
113+ case DASH_TMPL_ID_BANDWIDTH:
114+ n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, bit_rate);
115+ break;
116+ case DASH_TMPL_ID_TIME:
117+ n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, time);
118+ break;
119+ case DASH_TMPL_ID_UNDEFINED:
120+ // copy over one byte and advance
121+ av_strlcpy(&dst[dst_pos], t_cur, 2);
122+ n = 1;
123+ t_next = &t_cur[1];
124+ break;
125+ }
126+ // t_next points just past the processed identifier
127+ // n is the number of bytes that were attempted to be written to dst
128+ // (may have failed to write all because buffer_size).
129+
130+ // advance
131+ dst_pos += FFMIN(n, buffer_size - dst_pos - 1);
132+ t_cur = t_next;
133+ }
134+}
135+
136+
libavformat/dash.h+39−0
@@ -0,0 +1,39 @@
1+/*
2+ * MPEG-DASH ISO BMFF segmenter
3+ * Copyright (c) 2014 Martin Storsjo
4+ *
5+ * This file is part of FFmpeg.
6+ *
7+ * FFmpeg is free software; you can redistribute it and/or
8+ * modify it under the terms of the GNU Lesser General Public
9+ * License as published by the Free Software Foundation; either
10+ * version 2.1 of the License, or (at your option) any later version.
11+ *
12+ * FFmpeg 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+ * Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public
18+ * License along with FFmpeg; if not, write to the Free Software
19+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+ */
21+
22+#ifndef AVFORMAT_DASH_H
23+#define AVFORMAT_DASH_H
24+#include "avformat.h"
25+
26+// See ISO/IEC 23009-1:2014 5.3.9.4.4
27+typedef enum {
28+ DASH_TMPL_ID_UNDEFINED = -1,
29+ DASH_TMPL_ID_ESCAPE,
30+ DASH_TMPL_ID_REP_ID,
31+ DASH_TMPL_ID_NUMBER,
32+ DASH_TMPL_ID_BANDWIDTH,
33+ DASH_TMPL_ID_TIME,
34+} DASHTmplId;
35+
36+
37+void ff_dash_fill_tmpl_params(char *dst, size_t buffer_size, const char *template, int rep_id, int number, int bit_rate, int64_t time);
38+
39+#endif /* AVFORMAT_DASH_H */
libavformat/dashenc.c+4−126
@@ -39,16 +39,7 @@ · 38 unmodified lines
3939 #include "isom.h"
4040 #include "os_support.h"
4141 #include "url.h"
42−
43−// See ISO/IEC 23009-1:2014 5.3.9.4.4
44−typedef enum {
45− DASH_TMPL_ID_UNDEFINED = -1,
46− DASH_TMPL_ID_ESCAPE,
47− DASH_TMPL_ID_REP_ID,
48− DASH_TMPL_ID_NUMBER,
49− DASH_TMPL_ID_BANDWIDTH,
50− DASH_TMPL_ID_TIME,
51−} DASHTmplId;
42+#include "dash.h"
5243
5344 typedef struct Segment {
5445 char file[1024];
@@ -259,119 +250,6 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext · 204 unmodified lines
259250 }
260251 }
261252
262−static DASHTmplId dash_read_tmpl_id(const char *identifier, char *format_tag,
263− size_t format_tag_size, const char **ptr) {
264− const char *next_ptr;
265− DASHTmplId id_type = DASH_TMPL_ID_UNDEFINED;
266−
267− if (av_strstart(identifier, "$$", &next_ptr)) {
268− id_type = DASH_TMPL_ID_ESCAPE;
269− *ptr = next_ptr;
270− } else if (av_strstart(identifier, "$RepresentationID$", &next_ptr)) {
271− id_type = DASH_TMPL_ID_REP_ID;
272− // default to basic format, as $RepresentationID$ identifiers
273− // are not allowed to have custom format-tags.
274− av_strlcpy(format_tag, "%d", format_tag_size);
275− *ptr = next_ptr;
276− } else { // the following identifiers may have an explicit format_tag
277− if (av_strstart(identifier, "$Number", &next_ptr))
278− id_type = DASH_TMPL_ID_NUMBER;
279− else if (av_strstart(identifier, "$Bandwidth", &next_ptr))
280− id_type = DASH_TMPL_ID_BANDWIDTH;
281− else if (av_strstart(identifier, "$Time", &next_ptr))
282− id_type = DASH_TMPL_ID_TIME;
283− else
284− id_type = DASH_TMPL_ID_UNDEFINED;
285−
286− // next parse the dash format-tag and generate a c-string format tag
287− // (next_ptr now points at the first '%' at the beginning of the format-tag)
288− if (id_type != DASH_TMPL_ID_UNDEFINED) {
289− const char *number_format = (id_type == DASH_TMPL_ID_TIME) ? PRId64 : "d";
290− if (next_ptr[0] == '$') { // no dash format-tag
291− snprintf(format_tag, format_tag_size, "%%%s", number_format);
292− *ptr = &next_ptr[1];
293− } else {
294− const char *width_ptr;
295− // only tolerate single-digit width-field (i.e. up to 9-digit width)
296− if (av_strstart(next_ptr, "%0", &width_ptr) &&
297− av_isdigit(width_ptr[0]) &&
298− av_strstart(&width_ptr[1], "d$", &next_ptr)) {
299− // yes, we're using a format tag to build format_tag.
300− snprintf(format_tag, format_tag_size, "%s%c%s", "%0", width_ptr[0], number_format);
301− *ptr = next_ptr;
302− } else {
303− av_log(NULL, AV_LOG_WARNING, "Failed to parse format-tag beginning with %s. Expected either a "
304− "closing '$' character or a format-string like '%%0[width]d', "
305− "where width must be a single digit\n", next_ptr);
306− id_type = DASH_TMPL_ID_UNDEFINED;
307− }
308− }
309− }
310− }
311− return id_type;
312−}
313−
314−static void dash_fill_tmpl_params(char *dst, size_t buffer_size,
315− const char *template, int rep_id,
316− int number, int bit_rate,
317− int64_t time) {
318− int dst_pos = 0;
319− const char *t_cur = template;
320− while (dst_pos < buffer_size - 1 && *t_cur) {
321− char format_tag[7]; // May be "%d", "%0Xd", or "%0Xlld" (for $Time$), where X is in [0-9]
322− int n = 0;
323− DASHTmplId id_type;
324− const char *t_next = strchr(t_cur, '$'); // copy over everything up to the first '$' character
325− if (t_next) {
326− int num_copy_bytes = FFMIN(t_next - t_cur, buffer_size - dst_pos - 1);
327− av_strlcpy(&dst[dst_pos], t_cur, num_copy_bytes + 1);
328− // advance
329− dst_pos += num_copy_bytes;
330− t_cur = t_next;
331− } else { // no more DASH identifiers to substitute - just copy the rest over and break
332− av_strlcpy(&dst[dst_pos], t_cur, buffer_size - dst_pos);
333− break;
334− }
335−
336− if (dst_pos >= buffer_size - 1 || !*t_cur)
337− break;
338−
339− // t_cur is now pointing to a '$' character
340− id_type = dash_read_tmpl_id(t_cur, format_tag, sizeof(format_tag), &t_next);
341− switch (id_type) {
342− case DASH_TMPL_ID_ESCAPE:
343− av_strlcpy(&dst[dst_pos], "$", 2);
344− n = 1;
345− break;
346− case DASH_TMPL_ID_REP_ID:
347− n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, rep_id);
348− break;
349− case DASH_TMPL_ID_NUMBER:
350− n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, number);
351− break;
352− case DASH_TMPL_ID_BANDWIDTH:
353− n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, bit_rate);
354− break;
355− case DASH_TMPL_ID_TIME:
356− n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, time);
357− break;
358− case DASH_TMPL_ID_UNDEFINED:
359− // copy over one byte and advance
360− av_strlcpy(&dst[dst_pos], t_cur, 2);
361− n = 1;
362− t_next = &t_cur[1];
363− break;
364− }
365− // t_next points just past the processed identifier
366− // n is the number of bytes that were attempted to be written to dst
367− // (may have failed to write all because buffer_size).
368−
369− // advance
370− dst_pos += FFMIN(n, buffer_size - dst_pos - 1);
371− t_cur = t_next;
372− }
373−}
374−
375253 static char *xmlescape(const char *str) {
376254 int outlen = strlen(str)*3/2 + 6;
377255 char *out = av_realloc(NULL, outlen + 1);
@@ -660,11 +538,11 @@ static int dash_init(AVFormatContext *s) · 282 unmodified lines
660538
661539 if (c->single_file) {
662540 if (c->single_file_name)
663− dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->single_file_name, i, 0, os->bit_rate, 0);
541+ ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->single_file_name, i, 0, os->bit_rate, 0);
664542 else
665543 snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.m4s", basename, i);
666544 } else {
667− dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0);
545+ ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0);
668546 }
669547 snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
670548 ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, NULL);
@@ -865,7 +743,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) · 194 unmodified lines
865743 start_pos = avio_tell(os->ctx->pb);
866744
867745 if (!c->single_file) {
868− dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
746+ ff_dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
869747 snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);
870748 snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : "%s", full_path);
871749 ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, NULL);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t