[Ffmpeg-devel] [PATCH] Add support for the NXV container
Michael Niedermayer
michaelni
Fri Feb 23 12:59:37 CET 2007
Hi
On Thu, Feb 22, 2007 at 11:47:19PM -0800, Eric Werness wrote:
> The NXV file format is used by the Brando MP4 watch and a few other
> small gadgets that seem to be based on the same core.
>
> The format is documented here:
> http://wiki.multimedia.cx/index.php?title=NXV All of that is reverse
> engineered, so it's likely that some parts have errors or are incomplete.
>
> The decoder portion of this code has been tested against a dozen or so
> NXV files encoded with the official Windows software at different
> resolutions and quality levels.
>
> The encoder currently only support one quality level, but with different
> resolutions and framerates. The different quality levels, from a quick
> look, appear to just be telling the watch to scale by 2x2 or 4x4 instead
> of making the video a little window on the watch.
>
> The A/V sync is a bit problematic, some of which is probably due to the
> format relying on the MP3 bitrate staying stable and precise.
[...]
> +#include "avformat.h"
> +#include <float.h>
> +
> +#define AUDIO_PACKET_SIZE 500
> +#define INFO_SIZE 12
> +// Max frame size in bytes representable by the format
> +#define MAX_FRAME_SIZE (255*255*2)
> +// Number of frames buffered in the muxer
> +#define STAGING_FRAMES 3
the comments are not doxygen compatible
#define STAGING_FRAMES 3 ///< Number of frames buffered in the muxer
is what it should be
[...]
> + vst->codec->sample_aspect_ratio = av_d2q(1.0, 10000);
(AVRational){1,1}
> + // 500 bytes of 128kbit data is 32 packets/sec
> + vst->r_frame_rate = av_d2q(32, 10000);
dont set this variable
> + av_set_pts_info(vst, 33, 1, 90000);
this is wrong, set the correct timebase
[...]
> + } else if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
> + if (st->codec->height > 255) {
> + av_log(s, AV_LOG_ERROR, "height too large - try under 255\n");
> + return -1;
tabs and trailing whitespace is forbidden in svn
[...]
> + video_frame_rate = 1.0/av_q2d(st->codec->time_base);
float arithmetic is not allowed unless really required due to it breaking
regression tests besides it is inaccurate and leads to long term AV sync
issues
> +
> + ctx->width = st->codec->width;
> + ctx->height = st->codec->height;
why duplicate the variables?
> + ctx->frameSize = ctx->width * ctx->height * 2;
> +
> + if (ctx->frameSize > MAX_FRAME_SIZE) {
> + av_log(s, AV_LOG_ERROR, "Internal error: frame size greater than theoretical max\n");
> + return -1;
> + }
this should be an assert() if its impossible, if not its not an internal error
[...]
> + {
> + // bits/sec / (bits/byte * bytes/buffer) = buffers/sec. Max frame rate is 1 buffer per frame
> + double max_frame_rate = ((double)ctx->mp3_bit_rate)/(8.0*(double)AUDIO_PACKET_SIZE);
> + double rate_ratio = max_frame_rate / video_frame_rate;
> + double deviance = rate_ratio / round(rate_ratio);
> + double recommended = (rate_ratio > 1.0) ? (max_frame_rate / round(rate_ratio)) : max_frame_rate;
as already said float arithmetic is not allowed
[...]
> +static inline int min(int a, int b) {return (a<b)?a:b;}
FFMIN()
> +
> +static int nxv_write_audio(AVFormatContext *s, NXVContext *ctx,
> + AVCodecContext *enc, const uint8_t *buf, int size)
> +{
> + ByteIOContext *pb = &s->pb;
> +
> + // Loop just in case we get >AUDIO_PACKET_SIZE bytes in a packet
> + while (size) {
> + int copySize = min(AUDIO_PACKET_SIZE - ctx->curAudioSize, size);
> +
> + // Fill the buffer if possible
> + memcpy(ctx->audio+ctx->curAudioSize, buf, copySize);
> + ctx->curAudioSize += copySize;
> + buf += copySize;
> + size -= copySize;
> +
> + // Flush an audio buffer if it's full
> + assert(ctx->curAudioSize <= AUDIO_PACKET_SIZE);
> + if (ctx->curAudioSize == AUDIO_PACKET_SIZE) {
> + int i;
> +
> + put_buffer(pb, ctx->audio, AUDIO_PACKET_SIZE);
maybe this could be done simpler with a AVFifoBuffer?
[...]
> +static int nxv_write_video(AVFormatContext *s, NXVContext *ctx,
> + AVCodecContext *enc, const uint8_t *buf, int size)
> +{
> + int nextPut = (ctx->putFrame+1)%STAGING_FRAMES;
> + uint8_t *out = ctx->video[nextPut];
> + int i;
> +
> + if (nextPut == ctx->getFrame) {
> + av_log(s, AV_LOG_DEBUG, "Dropping a video frame to keep the streams in sync\n");
a muxer is not allowed to drop a frame, it MUST mux all or fatally fail
its the job of the user application (ffmpeg.c) to ensure that the framerate
is correct and acceptable
and its the job of AVOutputFormat.interleave_packet() to ensure correct
interleaving
[...]
> +static int nxv_read_packet(AVFormatContext *s,
> + AVPacket *pkt)
> +{
> + NXVContext *ctx = s->priv_data;
> + ByteIOContext *pb = &s->pb;
> + uint8_t info[INFO_SIZE];
> + uint32_t curSeq;
> + int ret = 0;
> +
> + if (ctx->mp3_bit_rate <= 0) {
> + int i;
> + for (i = 0; i < s->nb_streams; ++i) {
> + AVStream *st = s->streams[i];
> + if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
as you created the streams in fixed order in nxv_read_header() they still
are in that order and hie loop is not needed
> + ctx->mp3_bit_rate = st->codec->bit_rate;
> + if (ctx->mp3_bit_rate > 0) {
> + // The pts increment corresponds to AUDIO_PACKET_SIZE bytes of audio at the specified bit rate
> + // bufRate = (bitrate/8) / AUDIO_PACKET_SIZE
> + // pts/90000 = buf#/bufRate = (AUDIO_PACKET_SIZE*buf#) / (bitrate/8)
> + ctx->frame_pts_inc = (90000 * AUDIO_PACKET_SIZE) / (ctx->mp3_bit_rate/8);
set the timebase correctly with av_set_pts_info() in nxv_read_header()
[...]
> + for (i=0; i<ctx->expectingVideoBytes; i+=2) {
> + uint8_t t = pkt->data[i]; pkt->data[i] = pkt->data[i+1]; pkt->data[i+1] = t;
> + }
colorspace conversation in the demuxer is not allowed please add a pixfmt
to ../libavutil/avutil.h and dont forget little/big endian!
and conversation code to libswscale
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
No human being will ever know the Truth, for even if they happen to say it
by chance, they would not even known they had done so. -- Xenophanes
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20070223/a64fc804/attachment.pgp>
More information about the ffmpeg-devel
mailing list