2 * NUT (de)muxing via libnut
3 * copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org>
5 * This file is part of FFmpeg.
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.
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.
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
23 * @file libavformat/libnut.c
24 * NUT demuxing and muxing via libnut.
25 * @author Oded Shimon <ods15@ods15.dyndns.org>
32 #define ID_STRING "nut/multimedia container"
33 #define ID_LENGTH (strlen(ID_STRING) + 1)
37 nut_stream_header_tt
* s
;
40 static const AVCodecTag nut_tags
[] = {
41 { CODEC_ID_MPEG4
, MKTAG('m', 'p', '4', 'v') },
42 { CODEC_ID_MP3
, MKTAG('m', 'p', '3', ' ') },
43 { CODEC_ID_VORBIS
, MKTAG('v', 'r', 'b', 's') },
47 #if CONFIG_LIBNUT_MUXER
48 static int av_write(void * h
, size_t len
, const uint8_t * buf
) {
49 ByteIOContext
* bc
= h
;
50 put_buffer(bc
, buf
, len
);
51 //put_flush_packet(bc);
55 static int nut_write_header(AVFormatContext
* avf
) {
56 NUTContext
* priv
= avf
->priv_data
;
57 ByteIOContext
* bc
= avf
->pb
;
58 nut_muxer_opts_tt mopts
= {
63 .alloc
= { av_malloc
, av_realloc
, av_free
},
66 .max_distance
= 32768,
69 nut_stream_header_tt
* s
;
72 priv
->s
= s
= av_mallocz((avf
->nb_streams
+ 1) * sizeof*s
);
74 for (i
= 0; i
< avf
->nb_streams
; i
++) {
75 AVCodecContext
* codec
= avf
->streams
[i
]->codec
;
78 int num
, denom
, ssize
;
80 s
[i
].type
= codec
->codec_type
== CODEC_TYPE_VIDEO
? NUT_VIDEO_CLASS
: NUT_AUDIO_CLASS
;
82 if (codec
->codec_tag
) fourcc
= codec
->codec_tag
;
83 else fourcc
= ff_codec_get_tag(nut_tags
, codec
->codec_id
);
86 if (codec
->codec_type
== CODEC_TYPE_VIDEO
) fourcc
= ff_codec_get_tag(ff_codec_bmp_tags
, codec
->codec_id
);
87 if (codec
->codec_type
== CODEC_TYPE_AUDIO
) fourcc
= ff_codec_get_tag(ff_codec_wav_tags
, codec
->codec_id
);
91 s
[i
].fourcc
= av_malloc(s
[i
].fourcc_len
);
92 for (j
= 0; j
< s
[i
].fourcc_len
; j
++) s
[i
].fourcc
[j
] = (fourcc
>> (j
*8)) & 0xFF;
94 ff_parse_specific_params(codec
, &num
, &ssize
, &denom
);
95 av_set_pts_info(avf
->streams
[i
], 60, denom
, num
);
97 s
[i
].time_base
.num
= denom
;
98 s
[i
].time_base
.den
= num
;
101 s
[i
].decode_delay
= codec
->has_b_frames
;
102 s
[i
].codec_specific_len
= codec
->extradata_size
;
103 s
[i
].codec_specific
= codec
->extradata
;
105 if (codec
->codec_type
== CODEC_TYPE_VIDEO
) {
106 s
[i
].width
= codec
->width
;
107 s
[i
].height
= codec
->height
;
108 s
[i
].sample_width
= 0;
109 s
[i
].sample_height
= 0;
110 s
[i
].colorspace_type
= 0;
112 s
[i
].samplerate_num
= codec
->sample_rate
;
113 s
[i
].samplerate_denom
= 1;
114 s
[i
].channel_count
= codec
->channels
;
118 s
[avf
->nb_streams
].type
= -1;
119 priv
->nut
= nut_muxer_init(&mopts
, s
, NULL
);
124 static int nut_write_packet(AVFormatContext
* avf
, AVPacket
* pkt
) {
125 NUTContext
* priv
= avf
->priv_data
;
129 p
.stream
= pkt
->stream_index
;
131 p
.flags
= pkt
->flags
& PKT_FLAG_KEY
? NUT_FLAG_KEY
: 0;
134 nut_write_frame_reorder(priv
->nut
, &p
, pkt
->data
);
139 static int nut_write_trailer(AVFormatContext
* avf
) {
140 ByteIOContext
* bc
= avf
->pb
;
141 NUTContext
* priv
= avf
->priv_data
;
144 nut_muxer_uninit_reorder(priv
->nut
);
145 put_flush_packet(bc
);
147 for(i
= 0; priv
->s
[i
].type
!= -1; i
++ ) av_freep(&priv
->s
[i
].fourcc
);
153 AVOutputFormat libnut_muxer
= {
164 .flags
= AVFMT_GLOBALHEADER
,
166 #endif /* CONFIG_LIBNUT_MUXER */
168 static int nut_probe(AVProbeData
*p
) {
169 if (!memcmp(p
->buf
, ID_STRING
, ID_LENGTH
)) return AVPROBE_SCORE_MAX
;
174 static size_t av_read(void * h
, size_t len
, uint8_t * buf
) {
175 ByteIOContext
* bc
= h
;
176 return get_buffer(bc
, buf
, len
);
179 static off_t
av_seek(void * h
, long long pos
, int whence
) {
180 ByteIOContext
* bc
= h
;
181 if (whence
== SEEK_END
) {
182 pos
= url_fsize(bc
) + pos
;
185 return url_fseek(bc
, pos
, whence
);
188 static int nut_read_header(AVFormatContext
* avf
, AVFormatParameters
* ap
) {
189 NUTContext
* priv
= avf
->priv_data
;
190 ByteIOContext
* bc
= avf
->pb
;
191 nut_demuxer_opts_tt dopts
= {
199 .alloc
= { av_malloc
, av_realloc
, av_free
},
201 .cache_syncpoints
= 1,
203 nut_context_tt
* nut
= priv
->nut
= nut_demuxer_init(&dopts
);
204 nut_stream_header_tt
* s
;
207 if ((ret
= nut_read_headers(nut
, &s
, NULL
))) {
208 av_log(avf
, AV_LOG_ERROR
, " NUT error: %s\n", nut_error(ret
));
209 nut_demuxer_uninit(nut
);
215 for (i
= 0; s
[i
].type
!= -1 && i
< 2; i
++) {
216 AVStream
* st
= av_new_stream(avf
, i
);
219 for (j
= 0; j
< s
[i
].fourcc_len
&& j
< 8; j
++) st
->codec
->codec_tag
|= s
[i
].fourcc
[j
]<<(j
*8);
221 st
->codec
->has_b_frames
= s
[i
].decode_delay
;
223 st
->codec
->extradata_size
= s
[i
].codec_specific_len
;
224 if (st
->codec
->extradata_size
) {
225 st
->codec
->extradata
= av_mallocz(st
->codec
->extradata_size
);
226 memcpy(st
->codec
->extradata
, s
[i
].codec_specific
, st
->codec
->extradata_size
);
229 av_set_pts_info(avf
->streams
[i
], 60, s
[i
].time_base
.num
, s
[i
].time_base
.den
);
231 st
->duration
= s
[i
].max_pts
;
233 st
->codec
->codec_id
= ff_codec_get_id(nut_tags
, st
->codec
->codec_tag
);
236 case NUT_AUDIO_CLASS
:
237 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
238 if (st
->codec
->codec_id
== CODEC_ID_NONE
) st
->codec
->codec_id
= ff_codec_get_id(ff_codec_wav_tags
, st
->codec
->codec_tag
);
240 st
->codec
->channels
= s
[i
].channel_count
;
241 st
->codec
->sample_rate
= s
[i
].samplerate_num
/ s
[i
].samplerate_denom
;
243 case NUT_VIDEO_CLASS
:
244 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
245 if (st
->codec
->codec_id
== CODEC_ID_NONE
) st
->codec
->codec_id
= ff_codec_get_id(ff_codec_bmp_tags
, st
->codec
->codec_tag
);
247 st
->codec
->width
= s
[i
].width
;
248 st
->codec
->height
= s
[i
].height
;
249 st
->sample_aspect_ratio
.num
= s
[i
].sample_width
;
250 st
->sample_aspect_ratio
.den
= s
[i
].sample_height
;
253 if (st
->codec
->codec_id
== CODEC_ID_NONE
) av_log(avf
, AV_LOG_ERROR
, "Unknown codec?!\n");
259 static int nut_read_packet(AVFormatContext
* avf
, AVPacket
* pkt
) {
260 NUTContext
* priv
= avf
->priv_data
;
264 ret
= nut_read_next_packet(priv
->nut
, &pd
);
266 if (ret
|| av_new_packet(pkt
, pd
.len
) < 0) {
267 if (ret
!= NUT_ERR_EOF
)
268 av_log(avf
, AV_LOG_ERROR
, " NUT error: %s\n", nut_error(ret
));
272 if (pd
.flags
& NUT_FLAG_KEY
) pkt
->flags
|= PKT_FLAG_KEY
;
274 pkt
->stream_index
= pd
.stream
;
275 pkt
->pos
= url_ftell(avf
->pb
);
277 ret
= nut_read_frame(priv
->nut
, &pd
.len
, pkt
->data
);
282 static int nut_read_seek(AVFormatContext
* avf
, int stream_index
, int64_t target_ts
, int flags
) {
283 NUTContext
* priv
= avf
->priv_data
;
284 int active_streams
[] = { stream_index
, -1 };
285 double time_pos
= target_ts
* priv
->s
[stream_index
].time_base
.num
/ (double)priv
->s
[stream_index
].time_base
.den
;
287 if (nut_seek(priv
->nut
, time_pos
, 2*!(flags
& AVSEEK_FLAG_BACKWARD
), active_streams
)) return -1;
292 static int nut_read_close(AVFormatContext
*s
) {
293 NUTContext
* priv
= s
->priv_data
;
295 nut_demuxer_uninit(priv
->nut
);
300 AVInputFormat libnut_demuxer
= {
302 NULL_IF_CONFIG_SMALL("NUT format"),