Support playing SMV files.
Audio and video are interleaved via stream cur_dts - no idea how reliable this is. It also cannot display the video properly - it is stored with about 15 in a single JPEG frame, I cannot think of a reasonable way to implement this. Samples: http://samples.mplayerhq.hu/smv/ Format description: http://wiki.multimedia.cx/index.php?title=SMV Signed-off-by: Reimar Döffinger <Reimar.Doeffinger@gmx.de>
This commit is contained in:
		@@ -45,6 +45,13 @@ typedef struct {
 | 
			
		||||
    int last_duration;
 | 
			
		||||
    int w64;
 | 
			
		||||
    int write_bext;
 | 
			
		||||
    int64_t smv_data_ofs;
 | 
			
		||||
    int smv_block_size;
 | 
			
		||||
    int smv_frames_per_jpeg;
 | 
			
		||||
    int smv_block;
 | 
			
		||||
    int smv_last_stream;
 | 
			
		||||
    int smv_eof;
 | 
			
		||||
    int audio_eof;
 | 
			
		||||
} WAVContext;
 | 
			
		||||
 | 
			
		||||
#if CONFIG_WAV_MUXER
 | 
			
		||||
@@ -392,6 +399,8 @@ static int wav_read_header(AVFormatContext *s,
 | 
			
		||||
    int ret, got_fmt = 0;
 | 
			
		||||
    int64_t next_tag_ofs, data_ofs = -1;
 | 
			
		||||
 | 
			
		||||
    wav->smv_data_ofs = -1;
 | 
			
		||||
 | 
			
		||||
    /* check RIFF header */
 | 
			
		||||
    tag = avio_rl32(pb);
 | 
			
		||||
 | 
			
		||||
@@ -423,6 +432,7 @@ static int wav_read_header(AVFormatContext *s,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        AVStream *vst;
 | 
			
		||||
        size = next_tag(pb, &tag);
 | 
			
		||||
        next_tag_ofs = avio_tell(pb) + size;
 | 
			
		||||
 | 
			
		||||
@@ -468,6 +478,31 @@ static int wav_read_header(AVFormatContext *s,
 | 
			
		||||
            if ((ret = wav_parse_bext_tag(s, size)) < 0)
 | 
			
		||||
                return ret;
 | 
			
		||||
            break;
 | 
			
		||||
        case MKTAG('S','M','V','0'):
 | 
			
		||||
            // SMV file, a wav file with video appended.
 | 
			
		||||
            if (size != MKTAG('0','2','0','0')) {
 | 
			
		||||
                av_log(s, AV_LOG_ERROR, "Unknown SMV version found\n");
 | 
			
		||||
                goto break_loop;
 | 
			
		||||
            }
 | 
			
		||||
            av_log(s, AV_LOG_DEBUG, "Found SMV data\n");
 | 
			
		||||
            vst = av_new_stream(s, 1);
 | 
			
		||||
            if (!vst)
 | 
			
		||||
                return AVERROR(ENOMEM);
 | 
			
		||||
            avio_r8(pb);
 | 
			
		||||
            vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
 | 
			
		||||
            vst->codec->codec_id = CODEC_ID_MJPEG;
 | 
			
		||||
            vst->codec->width  = avio_rl24(pb);
 | 
			
		||||
            vst->codec->height = avio_rl24(pb);
 | 
			
		||||
            size = avio_rl24(pb);
 | 
			
		||||
            wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3;
 | 
			
		||||
            avio_rl24(pb);
 | 
			
		||||
            wav->smv_block_size = avio_rl24(pb);
 | 
			
		||||
            av_set_pts_info(vst, 32, 1, avio_rl24(pb));
 | 
			
		||||
            vst->duration = avio_rl24(pb);
 | 
			
		||||
            avio_rl24(pb);
 | 
			
		||||
            avio_rl24(pb);
 | 
			
		||||
            wav->smv_frames_per_jpeg = avio_rl24(pb);
 | 
			
		||||
            goto break_loop;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* seek to next tag unless we know that we'll run into EOF */
 | 
			
		||||
@@ -527,6 +562,45 @@ static int wav_read_packet(AVFormatContext *s,
 | 
			
		||||
    AVStream *st;
 | 
			
		||||
    WAVContext *wav = s->priv_data;
 | 
			
		||||
 | 
			
		||||
    if (wav->smv_data_ofs > 0) {
 | 
			
		||||
        int64_t audio_dts, video_dts;
 | 
			
		||||
smv_retry:
 | 
			
		||||
        audio_dts = s->streams[0]->cur_dts;
 | 
			
		||||
        video_dts = s->streams[1]->cur_dts;
 | 
			
		||||
        if (audio_dts != AV_NOPTS_VALUE && video_dts != AV_NOPTS_VALUE) {
 | 
			
		||||
            audio_dts = av_rescale_q(audio_dts, s->streams[0]->time_base, AV_TIME_BASE_Q);
 | 
			
		||||
            video_dts = av_rescale_q(video_dts, s->streams[1]->time_base, AV_TIME_BASE_Q);
 | 
			
		||||
            wav->smv_last_stream = video_dts >= audio_dts;
 | 
			
		||||
        }
 | 
			
		||||
        wav->smv_last_stream = !wav->smv_last_stream;
 | 
			
		||||
        wav->smv_last_stream |= wav->audio_eof;
 | 
			
		||||
        wav->smv_last_stream &= !wav->smv_eof;
 | 
			
		||||
        if (wav->smv_last_stream) {
 | 
			
		||||
            uint64_t old_pos = avio_tell(s->pb);
 | 
			
		||||
            uint64_t new_pos = wav->smv_data_ofs +
 | 
			
		||||
                wav->smv_block * wav->smv_block_size;
 | 
			
		||||
            if (avio_seek(s->pb, new_pos, SEEK_SET) < 0) {
 | 
			
		||||
                ret = AVERROR_EOF;
 | 
			
		||||
                goto smv_out;
 | 
			
		||||
            }
 | 
			
		||||
            size = avio_rl24(s->pb);
 | 
			
		||||
            ret  = av_get_packet(s->pb, pkt, size);
 | 
			
		||||
            if (ret < 0)
 | 
			
		||||
                goto smv_out;
 | 
			
		||||
            pkt->pos -= 3;
 | 
			
		||||
            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg;
 | 
			
		||||
            wav->smv_block++;
 | 
			
		||||
            pkt->stream_index = 1;
 | 
			
		||||
smv_out:
 | 
			
		||||
            avio_seek(s->pb, old_pos, SEEK_SET);
 | 
			
		||||
            if (ret == AVERROR_EOF) {
 | 
			
		||||
                wav->smv_eof = 1;
 | 
			
		||||
                goto smv_retry;
 | 
			
		||||
            }
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    st = s->streams[0];
 | 
			
		||||
 | 
			
		||||
    left = wav->data_end - avio_tell(s->pb);
 | 
			
		||||
@@ -535,8 +609,12 @@ static int wav_read_packet(AVFormatContext *s,
 | 
			
		||||
            left = find_guid(s->pb, guid_data) - 24;
 | 
			
		||||
        else
 | 
			
		||||
            left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a'));
 | 
			
		||||
        if (left < 0)
 | 
			
		||||
        if (left < 0) {
 | 
			
		||||
            wav->audio_eof = 1;
 | 
			
		||||
            if (wav->smv_data_ofs > 0 && !wav->smv_eof)
 | 
			
		||||
                goto smv_retry;
 | 
			
		||||
            return AVERROR_EOF;
 | 
			
		||||
        }
 | 
			
		||||
        wav->data_end= avio_tell(s->pb) + left;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -558,7 +636,18 @@ static int wav_read_packet(AVFormatContext *s,
 | 
			
		||||
static int wav_read_seek(AVFormatContext *s,
 | 
			
		||||
                         int stream_index, int64_t timestamp, int flags)
 | 
			
		||||
{
 | 
			
		||||
    WAVContext *wav = s->priv_data;
 | 
			
		||||
    AVStream *st;
 | 
			
		||||
    wav->smv_eof = 0;
 | 
			
		||||
    wav->audio_eof = 0;
 | 
			
		||||
    if (wav->smv_data_ofs > 0) {
 | 
			
		||||
        int64_t smv_timestamp = timestamp;
 | 
			
		||||
        if (stream_index == 0)
 | 
			
		||||
            smv_timestamp = av_rescale_q(timestamp, s->streams[0]->time_base, s->streams[1]->time_base);
 | 
			
		||||
        else
 | 
			
		||||
            timestamp = av_rescale_q(smv_timestamp, s->streams[1]->time_base, s->streams[0]->time_base);
 | 
			
		||||
        wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    st = s->streams[0];
 | 
			
		||||
    switch (st->codec->codec_id) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user