Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * WAV muxer
  3.  * Copyright (c) 2001, 2002 Fabrice Bellard
  4.  *
  5.  * Sony Wave64 muxer
  6.  * Copyright (c) 2012 Paul B Mahol
  7.  *
  8.  * WAV muxer RF64 support
  9.  * Copyright (c) 2013 Daniel Verkamp <daniel@drv.nu>
  10.  *
  11.  * This file is part of FFmpeg.
  12.  *
  13.  * FFmpeg is free software; you can redistribute it and/or
  14.  * modify it under the terms of the GNU Lesser General Public
  15.  * License as published by the Free Software Foundation; either
  16.  * version 2.1 of the License, or (at your option) any later version.
  17.  *
  18.  * FFmpeg is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  21.  * Lesser General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU Lesser General Public
  24.  * License along with FFmpeg; if not, write to the Free Software
  25.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26.  */
  27.  
  28. #include <stdint.h>
  29. #include <string.h>
  30.  
  31. #include "libavutil/dict.h"
  32. #include "libavutil/common.h"
  33. #include "libavutil/mathematics.h"
  34. #include "libavutil/opt.h"
  35.  
  36. #include "avformat.h"
  37. #include "avio.h"
  38. #include "avio_internal.h"
  39. #include "internal.h"
  40. #include "riff.h"
  41.  
  42. #define RF64_AUTO   (-1)
  43. #define RF64_NEVER  0
  44. #define RF64_ALWAYS 1
  45.  
  46. typedef struct WAVMuxContext {
  47.     const AVClass *class;
  48.     int64_t data;
  49.     int64_t fact_pos;
  50.     int64_t ds64;
  51.     int64_t minpts;
  52.     int64_t maxpts;
  53.     int last_duration;
  54.     int write_bext;
  55.     int rf64;
  56. } WAVMuxContext;
  57.  
  58. #if CONFIG_WAV_MUXER
  59. static inline void bwf_write_bext_string(AVFormatContext *s, const char *key, int maxlen)
  60. {
  61.     AVDictionaryEntry *tag;
  62.     int len = 0;
  63.  
  64.     if (tag = av_dict_get(s->metadata, key, NULL, 0)) {
  65.         len = strlen(tag->value);
  66.         len = FFMIN(len, maxlen);
  67.         avio_write(s->pb, tag->value, len);
  68.     }
  69.  
  70.     ffio_fill(s->pb, 0, maxlen - len);
  71. }
  72.  
  73. static void bwf_write_bext_chunk(AVFormatContext *s)
  74. {
  75.     AVDictionaryEntry *tmp_tag;
  76.     uint64_t time_reference = 0;
  77.     int64_t bext = ff_start_tag(s->pb, "bext");
  78.  
  79.     bwf_write_bext_string(s, "description", 256);
  80.     bwf_write_bext_string(s, "originator", 32);
  81.     bwf_write_bext_string(s, "originator_reference", 32);
  82.     bwf_write_bext_string(s, "origination_date", 10);
  83.     bwf_write_bext_string(s, "origination_time", 8);
  84.  
  85.     if (tmp_tag = av_dict_get(s->metadata, "time_reference", NULL, 0))
  86.         time_reference = strtoll(tmp_tag->value, NULL, 10);
  87.     avio_wl64(s->pb, time_reference);
  88.     avio_wl16(s->pb, 1);  // set version to 1
  89.  
  90.     if (tmp_tag = av_dict_get(s->metadata, "umid", NULL, 0)) {
  91.         unsigned char umidpart_str[17] = {0};
  92.         int i;
  93.         uint64_t umidpart;
  94.         int len = strlen(tmp_tag->value+2);
  95.  
  96.         for (i = 0; i < len/16; i++) {
  97.             memcpy(umidpart_str, tmp_tag->value + 2 + (i*16), 16);
  98.             umidpart = strtoll(umidpart_str, NULL, 16);
  99.             avio_wb64(s->pb, umidpart);
  100.         }
  101.         ffio_fill(s->pb, 0, 64 - i*8);
  102.     } else
  103.         ffio_fill(s->pb, 0, 64); // zero UMID
  104.  
  105.     ffio_fill(s->pb, 0, 190); // Reserved
  106.  
  107.     if (tmp_tag = av_dict_get(s->metadata, "coding_history", NULL, 0))
  108.         avio_put_str(s->pb, tmp_tag->value);
  109.  
  110.     ff_end_tag(s->pb, bext);
  111. }
  112.  
  113. static int wav_write_header(AVFormatContext *s)
  114. {
  115.     WAVMuxContext *wav = s->priv_data;
  116.     AVIOContext *pb = s->pb;
  117.     int64_t fmt;
  118.  
  119.     if (wav->rf64 == RF64_ALWAYS) {
  120.         ffio_wfourcc(pb, "RF64");
  121.         avio_wl32(pb, -1); /* RF64 chunk size: use size in ds64 */
  122.     } else {
  123.         ffio_wfourcc(pb, "RIFF");
  124.         avio_wl32(pb, 0); /* file length */
  125.     }
  126.  
  127.     ffio_wfourcc(pb, "WAVE");
  128.  
  129.     if (wav->rf64 != RF64_NEVER) {
  130.         /* write empty ds64 chunk or JUNK chunk to reserve space for ds64 */
  131.         ffio_wfourcc(pb, wav->rf64 == RF64_ALWAYS ? "ds64" : "JUNK");
  132.         avio_wl32(pb, 28); /* chunk size */
  133.         wav->ds64 = avio_tell(pb);
  134.         ffio_fill(pb, 0, 28);
  135.     }
  136.  
  137.     /* format header */
  138.     fmt = ff_start_tag(pb, "fmt ");
  139.     if (ff_put_wav_header(pb, s->streams[0]->codec) < 0) {
  140.         av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n",
  141.                s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
  142.         return -1;
  143.     }
  144.     ff_end_tag(pb, fmt);
  145.  
  146.     if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
  147.         && s->pb->seekable) {
  148.         wav->fact_pos = ff_start_tag(pb, "fact");
  149.         avio_wl32(pb, 0);
  150.         ff_end_tag(pb, wav->fact_pos);
  151.     }
  152.  
  153.     if (wav->write_bext)
  154.         bwf_write_bext_chunk(s);
  155.  
  156.     avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
  157.     wav->maxpts = wav->last_duration = 0;
  158.     wav->minpts = INT64_MAX;
  159.  
  160.     /* info header */
  161.     ff_riff_write_info(s);
  162.  
  163.     /* data header */
  164.     wav->data = ff_start_tag(pb, "data");
  165.  
  166.     avio_flush(pb);
  167.  
  168.     return 0;
  169. }
  170.  
  171. static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
  172. {
  173.     AVIOContext *pb  = s->pb;
  174.     WAVMuxContext    *wav = s->priv_data;
  175.     avio_write(pb, pkt->data, pkt->size);
  176.     if(pkt->pts != AV_NOPTS_VALUE) {
  177.         wav->minpts        = FFMIN(wav->minpts, pkt->pts);
  178.         wav->maxpts        = FFMAX(wav->maxpts, pkt->pts);
  179.         wav->last_duration = pkt->duration;
  180.     } else
  181.         av_log(s, AV_LOG_ERROR, "wav_write_packet: NOPTS\n");
  182.     return 0;
  183. }
  184.  
  185. static int wav_write_trailer(AVFormatContext *s)
  186. {
  187.     AVIOContext *pb  = s->pb;
  188.     WAVMuxContext    *wav = s->priv_data;
  189.     int64_t file_size, data_size;
  190.     int64_t number_of_samples = 0;
  191.     int rf64 = 0;
  192.  
  193.     avio_flush(pb);
  194.  
  195.     if (s->pb->seekable) {
  196.         /* update file size */
  197.         file_size = avio_tell(pb);
  198.         data_size = file_size - wav->data;
  199.         if (wav->rf64 == RF64_ALWAYS || (wav->rf64 == RF64_AUTO && file_size - 8 > UINT32_MAX)) {
  200.             rf64 = 1;
  201.         } else {
  202.             avio_seek(pb, 4, SEEK_SET);
  203.             avio_wl32(pb, (uint32_t)(file_size - 8));
  204.             avio_seek(pb, file_size, SEEK_SET);
  205.  
  206.             ff_end_tag(pb, wav->data);
  207.             avio_flush(pb);
  208.         }
  209.  
  210.         number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration,
  211.                                        s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num,
  212.                                        s->streams[0]->time_base.den);
  213.  
  214.         if(s->streams[0]->codec->codec_tag != 0x01) {
  215.             /* Update num_samps in fact chunk */
  216.             avio_seek(pb, wav->fact_pos, SEEK_SET);
  217.             if (rf64 || (wav->rf64 == RF64_AUTO && number_of_samples > UINT32_MAX)) {
  218.                 rf64 = 1;
  219.                 avio_wl32(pb, -1);
  220.             } else {
  221.                 avio_wl32(pb, number_of_samples);
  222.                 avio_seek(pb, file_size, SEEK_SET);
  223.                 avio_flush(pb);
  224.             }
  225.         }
  226.  
  227.         if (rf64) {
  228.             /* overwrite RIFF with RF64 */
  229.             avio_seek(pb, 0, SEEK_SET);
  230.             ffio_wfourcc(pb, "RF64");
  231.             avio_wl32(pb, -1);
  232.  
  233.             /* write ds64 chunk (overwrite JUNK if rf64 == RF64_AUTO) */
  234.             avio_seek(pb, wav->ds64 - 8, SEEK_SET);
  235.             ffio_wfourcc(pb, "ds64");
  236.             avio_wl32(pb, 28);                  /* ds64 chunk size */
  237.             avio_wl64(pb, file_size - 8);       /* RF64 chunk size */
  238.             avio_wl64(pb, data_size);           /* data chunk size */
  239.             avio_wl64(pb, number_of_samples);   /* fact chunk number of samples */
  240.             avio_wl32(pb, 0);                   /* number of table entries for non-'data' chunks */
  241.  
  242.             /* write -1 in data chunk size */
  243.             avio_seek(pb, wav->data - 4, SEEK_SET);
  244.             avio_wl32(pb, -1);
  245.  
  246.             avio_seek(pb, file_size, SEEK_SET);
  247.             avio_flush(pb);
  248.         }
  249.     }
  250.     return 0;
  251. }
  252.  
  253. #define OFFSET(x) offsetof(WAVMuxContext, x)
  254. #define ENC AV_OPT_FLAG_ENCODING_PARAM
  255. static const AVOption options[] = {
  256.     { "write_bext", "Write BEXT chunk.", OFFSET(write_bext), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ENC },
  257.     { "rf64",       "Use RF64 header rather than RIFF for large files.",    OFFSET(rf64), AV_OPT_TYPE_INT,   { .i64 = RF64_NEVER  },-1, 1, ENC, "rf64" },
  258.     { "auto",       "Write RF64 header if file grows large enough.",        0,            AV_OPT_TYPE_CONST, { .i64 = RF64_AUTO   }, 0, 0, ENC, "rf64" },
  259.     { "always",     "Always write RF64 header regardless of file size.",    0,            AV_OPT_TYPE_CONST, { .i64 = RF64_ALWAYS }, 0, 0, ENC, "rf64" },
  260.     { "never",      "Never write RF64 header regardless of file size.",     0,            AV_OPT_TYPE_CONST, { .i64 = RF64_NEVER  }, 0, 0, ENC, "rf64" },
  261.     { NULL },
  262. };
  263.  
  264. static const AVClass wav_muxer_class = {
  265.     .class_name = "WAV muxer",
  266.     .item_name  = av_default_item_name,
  267.     .option     = options,
  268.     .version    = LIBAVUTIL_VERSION_INT,
  269. };
  270.  
  271. AVOutputFormat ff_wav_muxer = {
  272.     .name              = "wav",
  273.     .long_name         = NULL_IF_CONFIG_SMALL("WAV / WAVE (Waveform Audio)"),
  274.     .mime_type         = "audio/x-wav",
  275.     .extensions        = "wav",
  276.     .priv_data_size    = sizeof(WAVMuxContext),
  277.     .audio_codec       = AV_CODEC_ID_PCM_S16LE,
  278.     .video_codec       = AV_CODEC_ID_NONE,
  279.     .write_header      = wav_write_header,
  280.     .write_packet      = wav_write_packet,
  281.     .write_trailer     = wav_write_trailer,
  282.     .flags             = AVFMT_TS_NONSTRICT,
  283.     .codec_tag         = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 },
  284.     .priv_class        = &wav_muxer_class,
  285. };
  286. #endif /* CONFIG_WAV_MUXER */
  287.  
  288. #if CONFIG_W64_MUXER
  289. #include "w64.h"
  290.  
  291. static void start_guid(AVIOContext *pb, const uint8_t *guid, int64_t *pos)
  292. {
  293.     *pos = avio_tell(pb);
  294.  
  295.     avio_write(pb, guid, 16);
  296.     avio_wl64(pb, INT64_MAX);
  297. }
  298.  
  299. static void end_guid(AVIOContext *pb, int64_t start)
  300. {
  301.     int64_t end, pos = avio_tell(pb);
  302.  
  303.     end = FFALIGN(pos, 8);
  304.     ffio_fill(pb, 0, end - pos);
  305.     avio_seek(pb, start + 16, SEEK_SET);
  306.     avio_wl64(pb, end - start);
  307.     avio_seek(pb, end, SEEK_SET);
  308. }
  309.  
  310. static int w64_write_header(AVFormatContext *s)
  311. {
  312.     WAVMuxContext *wav = s->priv_data;
  313.     AVIOContext *pb = s->pb;
  314.     int64_t start;
  315.     int ret;
  316.  
  317.     avio_write(pb, ff_w64_guid_riff, sizeof(ff_w64_guid_riff));
  318.     avio_wl64(pb, -1);
  319.     avio_write(pb, ff_w64_guid_wave, sizeof(ff_w64_guid_wave));
  320.     start_guid(pb, ff_w64_guid_fmt, &start);
  321.     if ((ret = ff_put_wav_header(pb, s->streams[0]->codec)) < 0) {
  322.         av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
  323.                s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
  324.         return ret;
  325.     }
  326.     end_guid(pb, start);
  327.  
  328.     if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
  329.         && s->pb->seekable) {
  330.         start_guid(pb, ff_w64_guid_fact, &wav->fact_pos);
  331.         avio_wl64(pb, 0);
  332.         end_guid(pb, wav->fact_pos);
  333.     }
  334.  
  335.     start_guid(pb, ff_w64_guid_data, &wav->data);
  336.  
  337.     return 0;
  338. }
  339.  
  340. static int w64_write_trailer(AVFormatContext *s)
  341. {
  342.     AVIOContext    *pb = s->pb;
  343.     WAVMuxContext *wav = s->priv_data;
  344.     int64_t file_size;
  345.  
  346.     if (pb->seekable) {
  347.         end_guid(pb, wav->data);
  348.  
  349.         file_size = avio_tell(pb);
  350.         avio_seek(pb, 16, SEEK_SET);
  351.         avio_wl64(pb, file_size);
  352.  
  353.         if (s->streams[0]->codec->codec_tag != 0x01) {
  354.             int64_t number_of_samples;
  355.  
  356.             number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration,
  357.                                            s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num,
  358.                                            s->streams[0]->time_base.den);
  359.             avio_seek(pb, wav->fact_pos + 24, SEEK_SET);
  360.             avio_wl64(pb, number_of_samples);
  361.         }
  362.  
  363.         avio_seek(pb, file_size, SEEK_SET);
  364.         avio_flush(pb);
  365.     }
  366.  
  367.     return 0;
  368. }
  369.  
  370. AVOutputFormat ff_w64_muxer = {
  371.     .name              = "w64",
  372.     .long_name         = NULL_IF_CONFIG_SMALL("Sony Wave64"),
  373.     .extensions        = "w64",
  374.     .priv_data_size    = sizeof(WAVMuxContext),
  375.     .audio_codec       = AV_CODEC_ID_PCM_S16LE,
  376.     .video_codec       = AV_CODEC_ID_NONE,
  377.     .write_header      = w64_write_header,
  378.     .write_packet      = wav_write_packet,
  379.     .write_trailer     = w64_write_trailer,
  380.     .flags             = AVFMT_TS_NONSTRICT,
  381.     .codec_tag         = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 },
  382. };
  383. #endif /* CONFIG_W64_MUXER */
  384.