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
132OBJS-$(CONFIG_CRC_MUXER) += crcenc.o132OBJS-$(CONFIG_CRC_MUXER) += crcenc.o
133OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o133OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o
134OBJS-$(CONFIG_DATA_MUXER) += rawenc.o134OBJS-$(CONFIG_DATA_MUXER) += rawenc.o
135OBJS-$(CONFIG_DASH_MUXER) += dashenc.o135OBJS-$(CONFIG_DASH_MUXER) += dash.o dashenc.o
136OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o136OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o
137OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o137OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o
138OBJS-$(CONFIG_DCSTR_DEMUXER) += dcstr.o138OBJS-$(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
23static 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
75void 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
27typedef 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
37void 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
39#include "isom.h"39#include "isom.h"
40#include "os_support.h"40#include "os_support.h"
41#include "url.h"41#include "url.h"
42 42#include "dash.h"
43// See ISO/IEC 23009-1:2014 5.3.9.4.4
44typedef 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;
52 43
53typedef struct Segment {44typedef struct Segment {
54 char file[1024];45 char file[1024];
@@ -259,119 +250,6 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext · 204 unmodified lines
259 }250 }
260}251}
261 252
262static 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
314static 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
375static char *xmlescape(const char *str) {253static char *xmlescape(const char *str) {
376 int outlen = strlen(str)*3/2 + 6;254 int outlen = strlen(str)*3/2 + 6;
377 char *out = av_realloc(NULL, outlen + 1);255 char *out = av_realloc(NULL, outlen + 1);
@@ -660,11 +538,11 @@ static int dash_init(AVFormatContext *s) · 282 unmodified lines
660 538
661 if (c->single_file) {539 if (c->single_file) {
662 if (c->single_file_name)540 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);
664 else542 else
665 snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.m4s", basename, i);543 snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.m4s", basename, i);
666 } else {544 } 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);
668 }546 }
669 snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);547 snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
670 ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, NULL);548 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
865 start_pos = avio_tell(os->ctx->pb);743 start_pos = avio_tell(os->ctx->pb);
866 744
867 if (!c->single_file) {745 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);
869 snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);747 snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);
870 snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : "%s", full_path);748 snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : "%s", full_path);
871 ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, NULL);749 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