1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * RSO muxer
3cabdff1aSopenharmony_ci * Copyright (c) 2001 Fabrice Bellard (original AU code)
4cabdff1aSopenharmony_ci * Copyright (c) 2010 Rafael Carre
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include "avformat.h"
24cabdff1aSopenharmony_ci#include "internal.h"
25cabdff1aSopenharmony_ci#include "rawenc.h"
26cabdff1aSopenharmony_ci#include "riff.h"
27cabdff1aSopenharmony_ci#include "rso.h"
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_cistatic int rso_write_header(AVFormatContext *s)
30cabdff1aSopenharmony_ci{
31cabdff1aSopenharmony_ci    AVIOContext  *pb  = s->pb;
32cabdff1aSopenharmony_ci    AVCodecParameters *par = s->streams[0]->codecpar;
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci    if (!par->codec_tag)
35cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ci    if (par->ch_layout.nb_channels != 1) {
38cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "RSO only supports mono\n");
39cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
40cabdff1aSopenharmony_ci    }
41cabdff1aSopenharmony_ci
42cabdff1aSopenharmony_ci    if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
43cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
44cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
45cabdff1aSopenharmony_ci    }
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci    /* XXX: find legal sample rates (if any) */
48cabdff1aSopenharmony_ci    if (par->sample_rate >= 1u<<16) {
49cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Sample rate must be < 65536\n");
50cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
51cabdff1aSopenharmony_ci    }
52cabdff1aSopenharmony_ci
53cabdff1aSopenharmony_ci    if (par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
54cabdff1aSopenharmony_ci        avpriv_report_missing_feature(s, "ADPCM in RSO");
55cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
56cabdff1aSopenharmony_ci    }
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci    /* format header */
59cabdff1aSopenharmony_ci    avio_wb16(pb, par->codec_tag);   /* codec ID */
60cabdff1aSopenharmony_ci    avio_wb16(pb, 0);                /* data size, will be written at EOF */
61cabdff1aSopenharmony_ci    avio_wb16(pb, par->sample_rate);
62cabdff1aSopenharmony_ci    avio_wb16(pb, 0x0000);           /* play mode ? (0x0000 = don't loop) */
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci    return 0;
65cabdff1aSopenharmony_ci}
66cabdff1aSopenharmony_ci
67cabdff1aSopenharmony_cistatic int rso_write_trailer(AVFormatContext *s)
68cabdff1aSopenharmony_ci{
69cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
70cabdff1aSopenharmony_ci    int64_t file_size;
71cabdff1aSopenharmony_ci    uint16_t coded_file_size;
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_ci    file_size = avio_tell(pb);
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_ci    if (file_size < 0)
76cabdff1aSopenharmony_ci        return file_size;
77cabdff1aSopenharmony_ci
78cabdff1aSopenharmony_ci    if (file_size > 0xffff + RSO_HEADER_SIZE) {
79cabdff1aSopenharmony_ci        av_log(s, AV_LOG_WARNING,
80cabdff1aSopenharmony_ci               "Output file is too big (%"PRId64" bytes >= 64kB)\n", file_size);
81cabdff1aSopenharmony_ci        coded_file_size = 0xffff;
82cabdff1aSopenharmony_ci    } else {
83cabdff1aSopenharmony_ci        coded_file_size = file_size - RSO_HEADER_SIZE;
84cabdff1aSopenharmony_ci    }
85cabdff1aSopenharmony_ci
86cabdff1aSopenharmony_ci    /* update file size */
87cabdff1aSopenharmony_ci    avio_seek(pb, 2, SEEK_SET);
88cabdff1aSopenharmony_ci    avio_wb16(pb, coded_file_size);
89cabdff1aSopenharmony_ci    avio_seek(pb, file_size, SEEK_SET);
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_ci    return 0;
92cabdff1aSopenharmony_ci}
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_ciconst AVOutputFormat ff_rso_muxer = {
95cabdff1aSopenharmony_ci    .name           =   "rso",
96cabdff1aSopenharmony_ci    .long_name      =   NULL_IF_CONFIG_SMALL("Lego Mindstorms RSO"),
97cabdff1aSopenharmony_ci    .extensions     =   "rso",
98cabdff1aSopenharmony_ci    .audio_codec    =   AV_CODEC_ID_PCM_U8,
99cabdff1aSopenharmony_ci    .video_codec    =   AV_CODEC_ID_NONE,
100cabdff1aSopenharmony_ci    .write_header   =   rso_write_header,
101cabdff1aSopenharmony_ci    .write_packet   =   ff_raw_write_packet,
102cabdff1aSopenharmony_ci    .write_trailer  =   rso_write_trailer,
103cabdff1aSopenharmony_ci    .codec_tag      =   ff_rso_codec_tags_list,
104cabdff1aSopenharmony_ci    .flags          =   AVFMT_NOTIMESTAMPS,
105cabdff1aSopenharmony_ci};
106