You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

765 lines
25KB

  1. /*
  2. * Copyright (c) 2012 Nicolas George
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public License
  8. * as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include "libavutil/avassert.h"
  21. #include "libavutil/avstring.h"
  22. #include "libavutil/intreadwrite.h"
  23. #include "libavutil/opt.h"
  24. #include "libavutil/parseutils.h"
  25. #include "libavutil/timestamp.h"
  26. #include "avformat.h"
  27. #include "internal.h"
  28. #include "url.h"
  29. typedef enum ConcatMatchMode {
  30. MATCH_ONE_TO_ONE,
  31. MATCH_EXACT_ID,
  32. } ConcatMatchMode;
  33. typedef struct ConcatStream {
  34. AVBSFContext *bsf;
  35. int out_stream_index;
  36. } ConcatStream;
  37. typedef struct {
  38. char *url;
  39. int64_t start_time;
  40. int64_t file_start_time;
  41. int64_t file_inpoint;
  42. int64_t duration;
  43. ConcatStream *streams;
  44. int64_t inpoint;
  45. int64_t outpoint;
  46. AVDictionary *metadata;
  47. int nb_streams;
  48. } ConcatFile;
  49. typedef struct {
  50. AVClass *class;
  51. ConcatFile *files;
  52. ConcatFile *cur_file;
  53. unsigned nb_files;
  54. AVFormatContext *avf;
  55. int safe;
  56. int seekable;
  57. int eof;
  58. ConcatMatchMode stream_match_mode;
  59. unsigned auto_convert;
  60. int segment_time_metadata;
  61. } ConcatContext;
  62. static int concat_probe(AVProbeData *probe)
  63. {
  64. return memcmp(probe->buf, "ffconcat version 1.0", 20) ?
  65. 0 : AVPROBE_SCORE_MAX;
  66. }
  67. static char *get_keyword(uint8_t **cursor)
  68. {
  69. char *ret = *cursor += strspn(*cursor, SPACE_CHARS);
  70. *cursor += strcspn(*cursor, SPACE_CHARS);
  71. if (**cursor) {
  72. *((*cursor)++) = 0;
  73. *cursor += strspn(*cursor, SPACE_CHARS);
  74. }
  75. return ret;
  76. }
  77. static int safe_filename(const char *f)
  78. {
  79. const char *start = f;
  80. for (; *f; f++) {
  81. /* A-Za-z0-9_- */
  82. if (!((unsigned)((*f | 32) - 'a') < 26 ||
  83. (unsigned)(*f - '0') < 10 || *f == '_' || *f == '-')) {
  84. if (f == start)
  85. return 0;
  86. else if (*f == '/')
  87. start = f + 1;
  88. else if (*f != '.')
  89. return 0;
  90. }
  91. }
  92. return 1;
  93. }
  94. #define FAIL(retcode) do { ret = (retcode); goto fail; } while(0)
  95. static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile,
  96. unsigned *nb_files_alloc)
  97. {
  98. ConcatContext *cat = avf->priv_data;
  99. ConcatFile *file;
  100. char *url = NULL;
  101. const char *proto;
  102. size_t url_len, proto_len;
  103. int ret;
  104. if (cat->safe > 0 && !safe_filename(filename)) {
  105. av_log(avf, AV_LOG_ERROR, "Unsafe file name '%s'\n", filename);
  106. FAIL(AVERROR(EPERM));
  107. }
  108. proto = avio_find_protocol_name(filename);
  109. proto_len = proto ? strlen(proto) : 0;
  110. if (!memcmp(filename, proto, proto_len) &&
  111. (filename[proto_len] == ':' || filename[proto_len] == ',')) {
  112. url = filename;
  113. filename = NULL;
  114. } else {
  115. url_len = strlen(avf->filename) + strlen(filename) + 16;
  116. if (!(url = av_malloc(url_len)))
  117. FAIL(AVERROR(ENOMEM));
  118. ff_make_absolute_url(url, url_len, avf->filename, filename);
  119. av_freep(&filename);
  120. }
  121. if (cat->nb_files >= *nb_files_alloc) {
  122. size_t n = FFMAX(*nb_files_alloc * 2, 16);
  123. ConcatFile *new_files;
  124. if (n <= cat->nb_files || n > SIZE_MAX / sizeof(*cat->files) ||
  125. !(new_files = av_realloc(cat->files, n * sizeof(*cat->files))))
  126. FAIL(AVERROR(ENOMEM));
  127. cat->files = new_files;
  128. *nb_files_alloc = n;
  129. }
  130. file = &cat->files[cat->nb_files++];
  131. memset(file, 0, sizeof(*file));
  132. *rfile = file;
  133. file->url = url;
  134. file->start_time = AV_NOPTS_VALUE;
  135. file->duration = AV_NOPTS_VALUE;
  136. file->inpoint = AV_NOPTS_VALUE;
  137. file->outpoint = AV_NOPTS_VALUE;
  138. return 0;
  139. fail:
  140. av_free(url);
  141. av_free(filename);
  142. return ret;
  143. }
  144. static int copy_stream_props(AVStream *st, AVStream *source_st)
  145. {
  146. int ret;
  147. if (st->codecpar->codec_id || !source_st->codecpar->codec_id) {
  148. if (st->codecpar->extradata_size < source_st->codecpar->extradata_size) {
  149. if (st->codecpar->extradata) {
  150. av_freep(&st->codecpar->extradata);
  151. st->codecpar->extradata_size = 0;
  152. }
  153. ret = ff_alloc_extradata(st->codecpar,
  154. source_st->codecpar->extradata_size);
  155. if (ret < 0)
  156. return ret;
  157. }
  158. memcpy(st->codecpar->extradata, source_st->codecpar->extradata,
  159. source_st->codecpar->extradata_size);
  160. return 0;
  161. }
  162. if ((ret = avcodec_parameters_copy(st->codecpar, source_st->codecpar)) < 0)
  163. return ret;
  164. st->r_frame_rate = source_st->r_frame_rate;
  165. st->avg_frame_rate = source_st->avg_frame_rate;
  166. st->time_base = source_st->time_base;
  167. st->sample_aspect_ratio = source_st->sample_aspect_ratio;
  168. av_dict_copy(&st->metadata, source_st->metadata, 0);
  169. return 0;
  170. }
  171. static int detect_stream_specific(AVFormatContext *avf, int idx)
  172. {
  173. ConcatContext *cat = avf->priv_data;
  174. AVStream *st = cat->avf->streams[idx];
  175. ConcatStream *cs = &cat->cur_file->streams[idx];
  176. const AVBitStreamFilter *filter;
  177. AVBSFContext *bsf;
  178. int ret;
  179. if (cat->auto_convert && st->codecpar->codec_id == AV_CODEC_ID_H264) {
  180. if (!st->codecpar->extradata_size ||
  181. (st->codecpar->extradata_size >= 3 && AV_RB24(st->codecpar->extradata) == 1) ||
  182. (st->codecpar->extradata_size >= 4 && AV_RB32(st->codecpar->extradata) == 1))
  183. return 0;
  184. av_log(cat->avf, AV_LOG_INFO,
  185. "Auto-inserting h264_mp4toannexb bitstream filter\n");
  186. filter = av_bsf_get_by_name("h264_mp4toannexb");
  187. if (!filter) {
  188. av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb bitstream filter "
  189. "required for H.264 streams\n");
  190. return AVERROR_BSF_NOT_FOUND;
  191. }
  192. ret = av_bsf_alloc(filter, &bsf);
  193. if (ret < 0)
  194. return ret;
  195. cs->bsf = bsf;
  196. ret = avcodec_parameters_copy(bsf->par_in, st->codecpar);
  197. if (ret < 0)
  198. return ret;
  199. ret = av_bsf_init(bsf);
  200. if (ret < 0)
  201. return ret;
  202. ret = avcodec_parameters_copy(st->codecpar, bsf->par_out);
  203. if (ret < 0)
  204. return ret;
  205. }
  206. return 0;
  207. }
  208. static int match_streams_one_to_one(AVFormatContext *avf)
  209. {
  210. ConcatContext *cat = avf->priv_data;
  211. AVStream *st;
  212. int i, ret;
  213. for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
  214. if (i < avf->nb_streams) {
  215. st = avf->streams[i];
  216. } else {
  217. if (!(st = avformat_new_stream(avf, NULL)))
  218. return AVERROR(ENOMEM);
  219. }
  220. if ((ret = copy_stream_props(st, cat->avf->streams[i])) < 0)
  221. return ret;
  222. cat->cur_file->streams[i].out_stream_index = i;
  223. }
  224. return 0;
  225. }
  226. static int match_streams_exact_id(AVFormatContext *avf)
  227. {
  228. ConcatContext *cat = avf->priv_data;
  229. AVStream *st;
  230. int i, j, ret;
  231. for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
  232. st = cat->avf->streams[i];
  233. for (j = 0; j < avf->nb_streams; j++) {
  234. if (avf->streams[j]->id == st->id) {
  235. av_log(avf, AV_LOG_VERBOSE,
  236. "Match slave stream #%d with stream #%d id 0x%x\n",
  237. i, j, st->id);
  238. if ((ret = copy_stream_props(avf->streams[j], st)) < 0)
  239. return ret;
  240. cat->cur_file->streams[i].out_stream_index = j;
  241. }
  242. }
  243. }
  244. return 0;
  245. }
  246. static int match_streams(AVFormatContext *avf)
  247. {
  248. ConcatContext *cat = avf->priv_data;
  249. ConcatStream *map;
  250. int i, ret;
  251. if (cat->cur_file->nb_streams >= cat->avf->nb_streams)
  252. return 0;
  253. map = av_realloc(cat->cur_file->streams,
  254. cat->avf->nb_streams * sizeof(*map));
  255. if (!map)
  256. return AVERROR(ENOMEM);
  257. cat->cur_file->streams = map;
  258. memset(map + cat->cur_file->nb_streams, 0,
  259. (cat->avf->nb_streams - cat->cur_file->nb_streams) * sizeof(*map));
  260. for (i = cat->cur_file->nb_streams; i < cat->avf->nb_streams; i++) {
  261. map[i].out_stream_index = -1;
  262. if ((ret = detect_stream_specific(avf, i)) < 0)
  263. return ret;
  264. }
  265. switch (cat->stream_match_mode) {
  266. case MATCH_ONE_TO_ONE:
  267. ret = match_streams_one_to_one(avf);
  268. break;
  269. case MATCH_EXACT_ID:
  270. ret = match_streams_exact_id(avf);
  271. break;
  272. default:
  273. ret = AVERROR_BUG;
  274. }
  275. if (ret < 0)
  276. return ret;
  277. cat->cur_file->nb_streams = cat->avf->nb_streams;
  278. return 0;
  279. }
  280. static int open_file(AVFormatContext *avf, unsigned fileno)
  281. {
  282. ConcatContext *cat = avf->priv_data;
  283. ConcatFile *file = &cat->files[fileno];
  284. int ret;
  285. if (cat->avf)
  286. avformat_close_input(&cat->avf);
  287. cat->avf = avformat_alloc_context();
  288. if (!cat->avf)
  289. return AVERROR(ENOMEM);
  290. cat->avf->flags |= avf->flags;
  291. cat->avf->interrupt_callback = avf->interrupt_callback;
  292. if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0)
  293. return ret;
  294. if ((ret = avformat_open_input(&cat->avf, file->url, NULL, NULL)) < 0 ||
  295. (ret = avformat_find_stream_info(cat->avf, NULL)) < 0) {
  296. av_log(avf, AV_LOG_ERROR, "Impossible to open '%s'\n", file->url);
  297. avformat_close_input(&cat->avf);
  298. return ret;
  299. }
  300. cat->cur_file = file;
  301. if (file->start_time == AV_NOPTS_VALUE)
  302. file->start_time = !fileno ? 0 :
  303. cat->files[fileno - 1].start_time +
  304. cat->files[fileno - 1].duration;
  305. file->file_start_time = (cat->avf->start_time == AV_NOPTS_VALUE) ? 0 : cat->avf->start_time;
  306. file->file_inpoint = (file->inpoint == AV_NOPTS_VALUE) ? file->file_start_time : file->inpoint;
  307. if (file->duration == AV_NOPTS_VALUE && file->outpoint != AV_NOPTS_VALUE)
  308. file->duration = file->outpoint - file->file_inpoint;
  309. if (cat->segment_time_metadata) {
  310. av_dict_set_int(&file->metadata, "lavf.concatdec.start_time", file->start_time, 0);
  311. if (file->duration != AV_NOPTS_VALUE)
  312. av_dict_set_int(&file->metadata, "lavf.concatdec.duration", file->duration, 0);
  313. }
  314. if ((ret = match_streams(avf)) < 0)
  315. return ret;
  316. if (file->inpoint != AV_NOPTS_VALUE) {
  317. if ((ret = avformat_seek_file(cat->avf, -1, INT64_MIN, file->inpoint, file->inpoint, 0)) < 0)
  318. return ret;
  319. }
  320. return 0;
  321. }
  322. static int concat_read_close(AVFormatContext *avf)
  323. {
  324. ConcatContext *cat = avf->priv_data;
  325. unsigned i, j;
  326. for (i = 0; i < cat->nb_files; i++) {
  327. av_freep(&cat->files[i].url);
  328. for (j = 0; j < cat->files[i].nb_streams; j++) {
  329. if (cat->files[i].streams[j].bsf)
  330. av_bsf_free(&cat->files[i].streams[j].bsf);
  331. }
  332. av_freep(&cat->files[i].streams);
  333. av_dict_free(&cat->files[i].metadata);
  334. }
  335. if (cat->avf)
  336. avformat_close_input(&cat->avf);
  337. av_freep(&cat->files);
  338. return 0;
  339. }
  340. static int concat_read_header(AVFormatContext *avf)
  341. {
  342. ConcatContext *cat = avf->priv_data;
  343. uint8_t buf[4096];
  344. uint8_t *cursor, *keyword;
  345. int ret, line = 0, i;
  346. unsigned nb_files_alloc = 0;
  347. ConcatFile *file = NULL;
  348. int64_t time = 0;
  349. while (1) {
  350. if ((ret = ff_get_line(avf->pb, buf, sizeof(buf))) <= 0)
  351. break;
  352. line++;
  353. cursor = buf;
  354. keyword = get_keyword(&cursor);
  355. if (!*keyword || *keyword == '#')
  356. continue;
  357. if (!strcmp(keyword, "file")) {
  358. char *filename = av_get_token((const char **)&cursor, SPACE_CHARS);
  359. if (!filename) {
  360. av_log(avf, AV_LOG_ERROR, "Line %d: filename required\n", line);
  361. FAIL(AVERROR_INVALIDDATA);
  362. }
  363. if ((ret = add_file(avf, filename, &file, &nb_files_alloc)) < 0)
  364. goto fail;
  365. } else if (!strcmp(keyword, "duration") || !strcmp(keyword, "inpoint") || !strcmp(keyword, "outpoint")) {
  366. char *dur_str = get_keyword(&cursor);
  367. int64_t dur;
  368. if (!file) {
  369. av_log(avf, AV_LOG_ERROR, "Line %d: %s without file\n",
  370. line, keyword);
  371. FAIL(AVERROR_INVALIDDATA);
  372. }
  373. if ((ret = av_parse_time(&dur, dur_str, 1)) < 0) {
  374. av_log(avf, AV_LOG_ERROR, "Line %d: invalid %s '%s'\n",
  375. line, keyword, dur_str);
  376. goto fail;
  377. }
  378. if (!strcmp(keyword, "duration"))
  379. file->duration = dur;
  380. else if (!strcmp(keyword, "inpoint"))
  381. file->inpoint = dur;
  382. else if (!strcmp(keyword, "outpoint"))
  383. file->outpoint = dur;
  384. } else if (!strcmp(keyword, "file_packet_metadata")) {
  385. char *metadata;
  386. if (!file) {
  387. av_log(avf, AV_LOG_ERROR, "Line %d: %s without file\n",
  388. line, keyword);
  389. FAIL(AVERROR_INVALIDDATA);
  390. }
  391. metadata = av_get_token((const char **)&cursor, SPACE_CHARS);
  392. if (!metadata) {
  393. av_log(avf, AV_LOG_ERROR, "Line %d: packet metadata required\n", line);
  394. FAIL(AVERROR_INVALIDDATA);
  395. }
  396. if ((ret = av_dict_parse_string(&file->metadata, metadata, "=", "", 0)) < 0) {
  397. av_log(avf, AV_LOG_ERROR, "Line %d: failed to parse metadata string\n", line);
  398. av_freep(&metadata);
  399. FAIL(AVERROR_INVALIDDATA);
  400. }
  401. av_freep(&metadata);
  402. } else if (!strcmp(keyword, "stream")) {
  403. if (!avformat_new_stream(avf, NULL))
  404. FAIL(AVERROR(ENOMEM));
  405. } else if (!strcmp(keyword, "exact_stream_id")) {
  406. if (!avf->nb_streams) {
  407. av_log(avf, AV_LOG_ERROR, "Line %d: exact_stream_id without stream\n",
  408. line);
  409. FAIL(AVERROR_INVALIDDATA);
  410. }
  411. avf->streams[avf->nb_streams - 1]->id =
  412. strtol(get_keyword(&cursor), NULL, 0);
  413. } else if (!strcmp(keyword, "ffconcat")) {
  414. char *ver_kw = get_keyword(&cursor);
  415. char *ver_val = get_keyword(&cursor);
  416. if (strcmp(ver_kw, "version") || strcmp(ver_val, "1.0")) {
  417. av_log(avf, AV_LOG_ERROR, "Line %d: invalid version\n", line);
  418. FAIL(AVERROR_INVALIDDATA);
  419. }
  420. if (cat->safe < 0)
  421. cat->safe = 1;
  422. } else {
  423. av_log(avf, AV_LOG_ERROR, "Line %d: unknown keyword '%s'\n",
  424. line, keyword);
  425. FAIL(AVERROR_INVALIDDATA);
  426. }
  427. }
  428. if (ret < 0)
  429. goto fail;
  430. if (!cat->nb_files)
  431. FAIL(AVERROR_INVALIDDATA);
  432. for (i = 0; i < cat->nb_files; i++) {
  433. if (cat->files[i].start_time == AV_NOPTS_VALUE)
  434. cat->files[i].start_time = time;
  435. else
  436. time = cat->files[i].start_time;
  437. if (cat->files[i].duration == AV_NOPTS_VALUE) {
  438. if (cat->files[i].inpoint == AV_NOPTS_VALUE || cat->files[i].outpoint == AV_NOPTS_VALUE)
  439. break;
  440. cat->files[i].duration = cat->files[i].outpoint - cat->files[i].inpoint;
  441. }
  442. time += cat->files[i].duration;
  443. }
  444. if (i == cat->nb_files) {
  445. avf->duration = time;
  446. cat->seekable = 1;
  447. }
  448. cat->stream_match_mode = avf->nb_streams ? MATCH_EXACT_ID :
  449. MATCH_ONE_TO_ONE;
  450. if ((ret = open_file(avf, 0)) < 0)
  451. goto fail;
  452. return 0;
  453. fail:
  454. concat_read_close(avf);
  455. return ret;
  456. }
  457. static int open_next_file(AVFormatContext *avf)
  458. {
  459. ConcatContext *cat = avf->priv_data;
  460. unsigned fileno = cat->cur_file - cat->files;
  461. if (cat->cur_file->duration == AV_NOPTS_VALUE)
  462. cat->cur_file->duration = cat->avf->duration - (cat->cur_file->file_inpoint - cat->cur_file->file_start_time);
  463. if (++fileno >= cat->nb_files) {
  464. cat->eof = 1;
  465. return AVERROR_EOF;
  466. }
  467. return open_file(avf, fileno);
  468. }
  469. static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
  470. {
  471. int ret;
  472. if (cs->bsf) {
  473. ret = av_bsf_send_packet(cs->bsf, pkt);
  474. if (ret < 0) {
  475. av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter "
  476. "failed to send input packet\n");
  477. av_packet_unref(pkt);
  478. return ret;
  479. }
  480. while (!ret)
  481. ret = av_bsf_receive_packet(cs->bsf, pkt);
  482. if (ret < 0 && (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)) {
  483. av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter "
  484. "failed to receive output packet\n");
  485. return ret;
  486. }
  487. }
  488. return 0;
  489. }
  490. /* Returns true if the packet dts is greater or equal to the specified outpoint. */
  491. static int packet_after_outpoint(ConcatContext *cat, AVPacket *pkt)
  492. {
  493. if (cat->cur_file->outpoint != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE) {
  494. return av_compare_ts(pkt->dts, cat->avf->streams[pkt->stream_index]->time_base,
  495. cat->cur_file->outpoint, AV_TIME_BASE_Q) >= 0;
  496. }
  497. return 0;
  498. }
  499. static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
  500. {
  501. ConcatContext *cat = avf->priv_data;
  502. int ret;
  503. int64_t delta;
  504. ConcatStream *cs;
  505. AVStream *st;
  506. if (cat->eof)
  507. return AVERROR_EOF;
  508. if (!cat->avf)
  509. return AVERROR(EIO);
  510. while (1) {
  511. ret = av_read_frame(cat->avf, pkt);
  512. if (ret == AVERROR_EOF) {
  513. if ((ret = open_next_file(avf)) < 0)
  514. return ret;
  515. continue;
  516. }
  517. if (ret < 0)
  518. return ret;
  519. if ((ret = match_streams(avf)) < 0) {
  520. av_packet_unref(pkt);
  521. return ret;
  522. }
  523. if (packet_after_outpoint(cat, pkt)) {
  524. av_packet_unref(pkt);
  525. if ((ret = open_next_file(avf)) < 0)
  526. return ret;
  527. continue;
  528. }
  529. cs = &cat->cur_file->streams[pkt->stream_index];
  530. if (cs->out_stream_index < 0) {
  531. av_packet_unref(pkt);
  532. continue;
  533. }
  534. pkt->stream_index = cs->out_stream_index;
  535. break;
  536. }
  537. if ((ret = filter_packet(avf, cs, pkt)))
  538. return ret;
  539. st = cat->avf->streams[pkt->stream_index];
  540. av_log(avf, AV_LOG_DEBUG, "file:%d stream:%d pts:%s pts_time:%s dts:%s dts_time:%s",
  541. (unsigned)(cat->cur_file - cat->files), pkt->stream_index,
  542. av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
  543. av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
  544. delta = av_rescale_q(cat->cur_file->start_time - cat->cur_file->file_inpoint,
  545. AV_TIME_BASE_Q,
  546. cat->avf->streams[pkt->stream_index]->time_base);
  547. if (pkt->pts != AV_NOPTS_VALUE)
  548. pkt->pts += delta;
  549. if (pkt->dts != AV_NOPTS_VALUE)
  550. pkt->dts += delta;
  551. av_log(avf, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n",
  552. av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
  553. av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
  554. if (cat->cur_file->metadata) {
  555. uint8_t* metadata;
  556. int metadata_len;
  557. char* packed_metadata = av_packet_pack_dictionary(cat->cur_file->metadata, &metadata_len);
  558. if (!packed_metadata)
  559. return AVERROR(ENOMEM);
  560. if (!(metadata = av_packet_new_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, metadata_len))) {
  561. av_freep(&packed_metadata);
  562. return AVERROR(ENOMEM);
  563. }
  564. memcpy(metadata, packed_metadata, metadata_len);
  565. av_freep(&packed_metadata);
  566. }
  567. return ret;
  568. }
  569. static void rescale_interval(AVRational tb_in, AVRational tb_out,
  570. int64_t *min_ts, int64_t *ts, int64_t *max_ts)
  571. {
  572. *ts = av_rescale_q (* ts, tb_in, tb_out);
  573. *min_ts = av_rescale_q_rnd(*min_ts, tb_in, tb_out,
  574. AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
  575. *max_ts = av_rescale_q_rnd(*max_ts, tb_in, tb_out,
  576. AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
  577. }
  578. static int try_seek(AVFormatContext *avf, int stream,
  579. int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
  580. {
  581. ConcatContext *cat = avf->priv_data;
  582. int64_t t0 = cat->cur_file->start_time - cat->cur_file->file_inpoint;
  583. ts -= t0;
  584. min_ts = min_ts == INT64_MIN ? INT64_MIN : min_ts - t0;
  585. max_ts = max_ts == INT64_MAX ? INT64_MAX : max_ts - t0;
  586. if (stream >= 0) {
  587. if (stream >= cat->avf->nb_streams)
  588. return AVERROR(EIO);
  589. rescale_interval(AV_TIME_BASE_Q, cat->avf->streams[stream]->time_base,
  590. &min_ts, &ts, &max_ts);
  591. }
  592. return avformat_seek_file(cat->avf, stream, min_ts, ts, max_ts, flags);
  593. }
  594. static int real_seek(AVFormatContext *avf, int stream,
  595. int64_t min_ts, int64_t ts, int64_t max_ts, int flags, AVFormatContext *cur_avf)
  596. {
  597. ConcatContext *cat = avf->priv_data;
  598. int ret, left, right;
  599. if (stream >= 0) {
  600. if (stream >= avf->nb_streams)
  601. return AVERROR(EINVAL);
  602. rescale_interval(avf->streams[stream]->time_base, AV_TIME_BASE_Q,
  603. &min_ts, &ts, &max_ts);
  604. }
  605. left = 0;
  606. right = cat->nb_files;
  607. while (right - left > 1) {
  608. int mid = (left + right) / 2;
  609. if (ts < cat->files[mid].start_time)
  610. right = mid;
  611. else
  612. left = mid;
  613. }
  614. if (cat->cur_file != &cat->files[left]) {
  615. if ((ret = open_file(avf, left)) < 0)
  616. return ret;
  617. } else {
  618. cat->avf = cur_avf;
  619. }
  620. ret = try_seek(avf, stream, min_ts, ts, max_ts, flags);
  621. if (ret < 0 &&
  622. left < cat->nb_files - 1 &&
  623. cat->files[left + 1].start_time < max_ts) {
  624. if (cat->cur_file == &cat->files[left])
  625. cat->avf = NULL;
  626. if ((ret = open_file(avf, left + 1)) < 0)
  627. return ret;
  628. ret = try_seek(avf, stream, min_ts, ts, max_ts, flags);
  629. }
  630. return ret;
  631. }
  632. static int concat_seek(AVFormatContext *avf, int stream,
  633. int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
  634. {
  635. ConcatContext *cat = avf->priv_data;
  636. ConcatFile *cur_file_saved = cat->cur_file;
  637. AVFormatContext *cur_avf_saved = cat->avf;
  638. int ret;
  639. if (!cat->seekable)
  640. return AVERROR(ESPIPE); /* XXX: can we use it? */
  641. if (flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME))
  642. return AVERROR(ENOSYS);
  643. cat->avf = NULL;
  644. if ((ret = real_seek(avf, stream, min_ts, ts, max_ts, flags, cur_avf_saved)) < 0) {
  645. if (cat->cur_file != cur_file_saved) {
  646. if (cat->avf)
  647. avformat_close_input(&cat->avf);
  648. }
  649. cat->avf = cur_avf_saved;
  650. cat->cur_file = cur_file_saved;
  651. } else {
  652. if (cat->cur_file != cur_file_saved) {
  653. avformat_close_input(&cur_avf_saved);
  654. }
  655. cat->eof = 0;
  656. }
  657. return ret;
  658. }
  659. #define OFFSET(x) offsetof(ConcatContext, x)
  660. #define DEC AV_OPT_FLAG_DECODING_PARAM
  661. static const AVOption options[] = {
  662. { "safe", "enable safe mode",
  663. OFFSET(safe), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, DEC },
  664. { "auto_convert", "automatically convert bitstream format",
  665. OFFSET(auto_convert), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DEC },
  666. { "segment_time_metadata", "output file segment start time and duration as packet metadata",
  667. OFFSET(segment_time_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
  668. { NULL }
  669. };
  670. static const AVClass concat_class = {
  671. .class_name = "concat demuxer",
  672. .item_name = av_default_item_name,
  673. .option = options,
  674. .version = LIBAVUTIL_VERSION_INT,
  675. };
  676. AVInputFormat ff_concat_demuxer = {
  677. .name = "concat",
  678. .long_name = NULL_IF_CONFIG_SMALL("Virtual concatenation script"),
  679. .priv_data_size = sizeof(ConcatContext),
  680. .read_probe = concat_probe,
  681. .read_header = concat_read_header,
  682. .read_packet = concat_read_packet,
  683. .read_close = concat_read_close,
  684. .read_seek2 = concat_seek,
  685. .priv_class = &concat_class,
  686. };