diff --git a/Changelog b/Changelog index caf9a53cc8..fd5863d2ff 100644 --- a/Changelog +++ b/Changelog @@ -41,6 +41,7 @@ easier to use. The changes are: * Presets in avconv are disabled, because only libx264 used them and presets for libx264 can now be specified using a private option '-preset '. +- XMV demuxer version 0.8: diff --git a/avconv.c b/avconv.c index c86e16bed9..85937fc365 100644 --- a/avconv.c +++ b/avconv.c @@ -109,15 +109,9 @@ typedef struct MetadataMap { static const OptionDef options[]; -#define MAX_FILES 100 #define MAX_STREAMS 1024 /* arbitrary sanity check value */ static const char *last_asked_format = NULL; -static double *ts_scale; -static int nb_ts_scale; - -static AVFormatContext *output_files[MAX_FILES]; -static AVDictionary *output_opts[MAX_FILES]; -static int nb_output_files = 0; +static AVDictionary *ts_scale; static StreamMap *stream_maps = NULL; static int nb_stream_maps; @@ -294,11 +288,9 @@ typedef struct OutputStream { int sws_flags; AVDictionary *opts; + int is_past_recording_time; } OutputStream; -static OutputStream **output_streams_for_file[MAX_FILES] = { NULL }; -static int nb_output_streams_for_file[MAX_FILES] = { 0 }; - typedef struct InputStream { int file_index; AVStream *st; @@ -313,7 +305,6 @@ typedef struct InputStream { double ts_scale; int is_start; /* is 1 at the start and after a discontinuity */ int showed_multi_packet_warning; - int is_past_recording_time; AVDictionary *opts; } InputStream; @@ -332,11 +323,24 @@ typedef struct InputFile { static struct termios oldtty; #endif +typedef struct OutputFile { + AVFormatContext *ctx; + AVDictionary *opts; + int ost_index; /* index of the first stream in output_streams */ + int64_t recording_time; /* desired length of the resulting file in microseconds */ + int64_t start_time; /* start time in microseconds */ +} OutputFile; + static InputStream *input_streams = NULL; static int nb_input_streams = 0; static InputFile *input_files = NULL; static int nb_input_files = 0; +static OutputStream *output_streams = NULL; +static int nb_output_streams = 0; +static OutputFile *output_files = NULL; +static int nb_output_files = 0; + #if CONFIG_AVFILTER static int configure_video_filters(InputStream *ist, OutputStream *ost) @@ -516,12 +520,11 @@ static int exit_program(int ret) /* close files */ for(i=0;ioformat->flags & AVFMT_NOFILE) && s->pb) avio_close(s->pb); avformat_free_context(s); - av_free(output_streams_for_file[i]); - av_dict_free(&output_opts[i]); + av_dict_free(&output_files[i].opts); } for(i=0;isync_ist; - return (double)(ist->pts - start_time)/AV_TIME_BASE; + OutputFile *of = &output_files[ost->file_index]; + return (double)(ist->pts - of->start_time)/AV_TIME_BASE; } static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){ @@ -1071,14 +1077,85 @@ static void do_subtitle_out(AVFormatContext *s, static int bit_buffer_size= 1024*256; static uint8_t *bit_buffer= NULL; +static void do_video_resample(OutputStream *ost, + InputStream *ist, + AVFrame *in_picture, + AVFrame **out_picture) +{ + int resample_changed = 0; + AVCodecContext *dec = ist->st->codec; + *out_picture = in_picture; + + resample_changed = ost->resample_width != dec->width || + ost->resample_height != dec->height || + ost->resample_pix_fmt != dec->pix_fmt; + +#if !CONFIG_AVFILTER + if (resample_changed) { + av_log(NULL, AV_LOG_INFO, + "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", + ist->file_index, ist->st->index, + ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt), + dec->width , dec->height , av_get_pix_fmt_name(dec->pix_fmt)); + ost->resample_width = dec->width; + ost->resample_height = dec->height; + ost->resample_pix_fmt = dec->pix_fmt; + } + + ost->video_resample = dec->width != enc->width || + dec->height != enc->height || + dec->pix_fmt != enc->pix_fmt; + + if (ost->video_resample) { + *out_picture = &ost->resample_frame; + if (!ost->img_resample_ctx || resample_changed) { + /* initialize the destination picture */ + if (!ost->resample_frame.data[0]) { + avcodec_get_frame_defaults(&ost->resample_frame); + if (avpicture_alloc((AVPicture *)&ost->resample_frame, enc->pix_fmt, + enc->width, enc->height)) { + fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n"); + exit_program(1); + } + } + /* initialize a new scaler context */ + sws_freeContext(ost->img_resample_ctx); + ost->img_resample_ctx = sws_getContext(dec->width, dec->height, dec->pix_fmt, + enc->width, enc->height, enc->pix_fmt, + ost->sws_flags, NULL, NULL, NULL); + if (ost->img_resample_ctx == NULL) { + fprintf(stderr, "Cannot get resampling context\n"); + exit_program(1); + } + } + sws_scale(ost->img_resample_ctx, in_picture->data, in_picture->linesize, + 0, ost->resample_height, (*out_picture)->data, (*out_picture)->linesize); + } +#else + if (resample_changed) { + avfilter_graph_free(&ost->graph); + if (configure_video_filters(ist, ost)) { + fprintf(stderr, "Error reinitialising filters!\n"); + exit_program(1); + } + } +#endif + if (resample_changed) { + ost->resample_width = dec->width; + ost->resample_height = dec->height; + ost->resample_pix_fmt = dec->pix_fmt; + } +} + + static void do_video_out(AVFormatContext *s, OutputStream *ost, InputStream *ist, AVFrame *in_picture, int *frame_size, float quality) { - int nb_frames, i, ret, av_unused resample_changed; - AVFrame *final_picture, *formatted_picture; + int nb_frames, i, ret, format_video_sync; + AVFrame *final_picture; AVCodecContext *enc, *dec; double sync_ipts; @@ -1092,12 +1169,16 @@ static void do_video_out(AVFormatContext *s, *frame_size = 0; - if(video_sync_method){ + format_video_sync = video_sync_method; + if (format_video_sync < 0) + format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? 2 : 1; + + if (format_video_sync) { double vdelta = sync_ipts - ost->sync_opts; //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c if (vdelta < -1.1) nb_frames = 0; - else if (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){ + else if (format_video_sync == 2) { if(vdelta<=-0.6){ nb_frames=0; }else if(vdelta>0.6) @@ -1121,68 +1202,7 @@ static void do_video_out(AVFormatContext *s, if (nb_frames <= 0) return; - formatted_picture = in_picture; - final_picture = formatted_picture; - - resample_changed = ost->resample_width != dec->width || - ost->resample_height != dec->height || - ost->resample_pix_fmt != dec->pix_fmt; - -#if !CONFIG_AVFILTER - if (resample_changed) { - av_log(NULL, AV_LOG_INFO, - "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", - ist->file_index, ist->st->index, - ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt), - dec->width , dec->height , av_get_pix_fmt_name(dec->pix_fmt)); - ost->resample_width = dec->width; - ost->resample_height = dec->height; - ost->resample_pix_fmt = dec->pix_fmt; - } - - ost->video_resample = dec->width != enc->width || - dec->height != enc->height || - dec->pix_fmt != enc->pix_fmt; - - if (ost->video_resample) { - final_picture = &ost->resample_frame; - if (!ost->img_resample_ctx || resample_changed) { - /* initialize the destination picture */ - if (!ost->resample_frame.data[0]) { - avcodec_get_frame_defaults(&ost->resample_frame); - if (avpicture_alloc((AVPicture *)&ost->resample_frame, enc->pix_fmt, - enc->width, enc->height)) { - fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n"); - exit_program(1); - } - } - /* initialize a new scaler context */ - sws_freeContext(ost->img_resample_ctx); - ost->img_resample_ctx = sws_getContext(dec->width, dec->height, dec->pix_fmt, - enc->width, enc->height, enc->pix_fmt, - ost->sws_flags, NULL, NULL, NULL); - if (ost->img_resample_ctx == NULL) { - fprintf(stderr, "Cannot get resampling context\n"); - exit_program(1); - } - } - sws_scale(ost->img_resample_ctx, formatted_picture->data, formatted_picture->linesize, - 0, ost->resample_height, final_picture->data, final_picture->linesize); - } -#else - if (resample_changed) { - avfilter_graph_free(&ost->graph); - if (configure_video_filters(ist, ost)) { - fprintf(stderr, "Error reinitialising filters!\n"); - exit_program(1); - } - } -#endif - if (resample_changed) { - ost->resample_width = dec->width; - ost->resample_height = dec->height; - ost->resample_pix_fmt = dec->pix_fmt; - } + do_video_resample(ost, ist, in_picture, &final_picture); /* duplicates frame if needed */ for(i=0;ipb); if(total_size<0) // FIXME improve avio_size() so it works with non seekable output too @@ -1346,7 +1366,7 @@ static void print_report(AVFormatContext **output_files, vid = 0; for(i=0;ist->codec; if (!ost->st->stream_copy && enc->coded_frame) q = enc->coded_frame->quality/(float)FF_QP2LAMBDA; @@ -1448,7 +1468,7 @@ static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_ /* pkt = NULL means EOF (needed to flush decoder buffers) */ static int output_packet(InputStream *ist, int ist_index, - OutputStream **ost_table, int nb_ostreams, + OutputStream *ost_table, int nb_ostreams, const AVPacket *pkt) { AVFormatContext *os; @@ -1595,22 +1615,6 @@ static int output_packet(InputStream *ist, int ist_index, avpkt.size = 0; } -#if CONFIG_AVFILTER - if(ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) - if (start_time == 0 || ist->pts >= start_time) { - for(i=0;iinput_video_filter && ost->source_index == ist_index) { - if (!picture.sample_aspect_ratio.num) - picture.sample_aspect_ratio = ist->st->sample_aspect_ratio; - picture.pts = ist->pts; - - av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, AV_VSRC_BUF_FLAG_OVERWRITE); - } - } - } -#endif - // preprocess audio (volume) if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { if (audio_volume != 256) { @@ -1634,130 +1638,149 @@ static int output_packet(InputStream *ist, int ist_index, } /* if output time reached then transcode raw format, encode packets and output them */ - if (start_time == 0 || ist->pts >= start_time) - for(i=0;isource_index != ist_index) + continue; + + if (of->start_time && ist->pts < of->start_time) + continue; + + if (of->recording_time != INT64_MAX && + av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time, + (AVRational){1, 1000000}) >= 0) { + ost->is_past_recording_time = 1; + continue; + } - ost = ost_table[i]; - if (ost->source_index == ist_index) { #if CONFIG_AVFILTER - frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || - !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]); - while (frame_available) { - if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) { - AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base; - if (av_vsink_buffer_get_video_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0) - goto cont; - if (ost->picref) { - avfilter_fill_frame_from_video_buffer_ref(&picture, ost->picref); - ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); - } + if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + ost->input_video_filter) { + if (!picture.sample_aspect_ratio.num) + picture.sample_aspect_ratio = ist->st->sample_aspect_ratio; + picture.pts = ist->pts; + + av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, AV_VSRC_BUF_FLAG_OVERWRITE); + } + frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || + !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]); + while (frame_available) { + if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) { + AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base; + if (av_vsink_buffer_get_video_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0) + goto cont; + if (ost->picref) { + avfilter_fill_frame_from_video_buffer_ref(&picture, ost->picref); + ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); } + } #endif - os = output_files[ost->file_index]; + os = output_files[ost->file_index].ctx; - /* set the input output pts pairs */ - //ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE; + /* set the input output pts pairs */ + //ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE; - if (ost->encoding_needed) { - av_assert0(ist->decoding_needed); - switch(ost->st->codec->codec_type) { - case AVMEDIA_TYPE_AUDIO: - do_audio_out(os, ost, ist, decoded_data_buf, decoded_data_size); - break; - case AVMEDIA_TYPE_VIDEO: + if (ost->encoding_needed) { + av_assert0(ist->decoding_needed); + switch(ost->st->codec->codec_type) { + case AVMEDIA_TYPE_AUDIO: + do_audio_out(os, ost, ist, decoded_data_buf, decoded_data_size); + break; + case AVMEDIA_TYPE_VIDEO: #if CONFIG_AVFILTER - if (ost->picref->video && !ost->frame_aspect_ratio) - ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio; + if (ost->picref->video && !ost->frame_aspect_ratio) + ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio; #endif - do_video_out(os, ost, ist, &picture, &frame_size, - same_quant ? quality : ost->st->codec->global_quality); - if (vstats_filename && frame_size) - do_video_stats(os, ost, frame_size); - break; - case AVMEDIA_TYPE_SUBTITLE: - do_subtitle_out(os, ost, ist, &subtitle, - pkt->pts); - break; - default: - abort(); - } - } else { - AVFrame avframe; //FIXME/XXX remove this - AVPicture pict; - AVPacket opkt; - int64_t ost_tb_start_time= av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base); + do_video_out(os, ost, ist, &picture, &frame_size, + same_quant ? quality : ost->st->codec->global_quality); + if (vstats_filename && frame_size) + do_video_stats(os, ost, frame_size); + break; + case AVMEDIA_TYPE_SUBTITLE: + do_subtitle_out(os, ost, ist, &subtitle, + pkt->pts); + break; + default: + abort(); + } + } else { + AVFrame avframe; //FIXME/XXX remove this + AVPicture pict; + AVPacket opkt; + int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); + av_init_packet(&opkt); - av_init_packet(&opkt); - - if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes) + if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes) #if !CONFIG_AVFILTER - continue; + continue; #else - goto cont; + goto cont; #endif - /* no reencoding needed : output the packet directly */ - /* force the input stream PTS */ + /* no reencoding needed : output the packet directly */ + /* force the input stream PTS */ - avcodec_get_frame_defaults(&avframe); - ost->st->codec->coded_frame= &avframe; - avframe.key_frame = pkt->flags & AV_PKT_FLAG_KEY; + avcodec_get_frame_defaults(&avframe); + ost->st->codec->coded_frame= &avframe; + avframe.key_frame = pkt->flags & AV_PKT_FLAG_KEY; - if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) - audio_size += data_size; - else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - video_size += data_size; - ost->sync_opts++; - } - - opkt.stream_index= ost->index; - if(pkt->pts != AV_NOPTS_VALUE) - opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time; - else - opkt.pts= AV_NOPTS_VALUE; - - if (pkt->dts == AV_NOPTS_VALUE) - opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base); - else - opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); - opkt.dts -= ost_tb_start_time; - - opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); - opkt.flags= pkt->flags; - - //FIXME remove the following 2 lines they shall be replaced by the bitstream filters - if( ost->st->codec->codec_id != CODEC_ID_H264 - && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO - && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO - ) { - if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY)) - opkt.destruct= av_destruct_packet; - } else { - opkt.data = data_buf; - opkt.size = data_size; - } - - if (os->oformat->flags & AVFMT_RAWPICTURE) { - /* store AVPicture in AVPacket, as expected by the output format */ - avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height); - opkt.data = (uint8_t *)&pict; - opkt.size = sizeof(AVPicture); - opkt.flags |= AV_PKT_FLAG_KEY; - } - write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters); - ost->st->codec->frame_number++; - ost->frame_number++; - av_free_packet(&opkt); + if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + audio_size += data_size; + else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + video_size += data_size; + ost->sync_opts++; } + + opkt.stream_index= ost->index; + if(pkt->pts != AV_NOPTS_VALUE) + opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time; + else + opkt.pts= AV_NOPTS_VALUE; + + if (pkt->dts == AV_NOPTS_VALUE) + opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base); + else + opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); + opkt.dts -= ost_tb_start_time; + + opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); + opkt.flags= pkt->flags; + + //FIXME remove the following 2 lines they shall be replaced by the bitstream filters + if( ost->st->codec->codec_id != CODEC_ID_H264 + && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO + && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO + ) { + if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY)) + opkt.destruct= av_destruct_packet; + } else { + opkt.data = data_buf; + opkt.size = data_size; + } + + if (os->oformat->flags & AVFMT_RAWPICTURE) { + /* store AVPicture in AVPacket, as expected by the output format */ + avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height); + opkt.data = (uint8_t *)&pict; + opkt.size = sizeof(AVPicture); + opkt.flags |= AV_PKT_FLAG_KEY; + } + write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters); + ost->st->codec->frame_number++; + ost->frame_number++; + av_free_packet(&opkt); + } #if CONFIG_AVFILTER - cont: - frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && - ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]); + cont: + frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && + ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]); + if (ost->picref) avfilter_unref_buffer(ost->picref); - } + } #endif - } } av_free(buffer_to_free); @@ -1772,10 +1795,10 @@ static int output_packet(InputStream *ist, int ist_index, /* EOF handling */ for(i=0;isource_index == ist_index) { AVCodecContext *enc= ost->st->codec; - os = output_files[ost->file_index]; + os = output_files[ost->file_index].ctx; if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1) continue; @@ -1856,105 +1879,66 @@ static int output_packet(InputStream *ist, int ist_index, return 0; } -static void print_sdp(AVFormatContext **avc, int n) +static void print_sdp(OutputFile *output_files, int n) { char sdp[2048]; + int i; + AVFormatContext **avc = av_malloc(sizeof(*avc)*n); + + if (!avc) + exit_program(1); + for (i = 0; i < n; i++) + avc[i] = output_files[i].ctx; av_sdp_create(avc, n, sdp, sizeof(sdp)); printf("SDP:\n%s\n", sdp); fflush(stdout); + av_freep(&avc); } /* * The following code is the main loop of the file converter */ -static int transcode(AVFormatContext **output_files, +static int transcode(OutputFile *output_files, int nb_output_files, InputFile *input_files, int nb_input_files) { - int ret = 0, i, j, k, n, nb_ostreams = 0, step; - + int ret = 0, i, j, step; AVFormatContext *is, *os; AVCodecContext *codec, *icodec; - OutputStream *ost, **ost_table = NULL; + OutputStream *ost; InputStream *ist; char error[1024]; int key; int want_sdp = 1; - uint8_t no_packet[MAX_FILES]={0}; + uint8_t *no_packet; int no_packet_count=0; int nb_frame_threshold[AVMEDIA_TYPE_NB]={0}; int nb_streams[AVMEDIA_TYPE_NB]={0}; + if (!(no_packet = av_mallocz(nb_input_files))) + exit_program(1); + if (rate_emu) for (i = 0; i < nb_input_streams; i++) input_streams[i].start = av_gettime(); /* output stream init */ - nb_ostreams = 0; for(i=0;inb_streams && !(os->oformat->flags & AVFMT_NOSTREAMS)) { - av_dump_format(output_files[i], i, output_files[i]->filename, 1); + av_dump_format(os, i, os->filename, 1); fprintf(stderr, "Output file #%d does not contain any stream\n", i); ret = AVERROR(EINVAL); goto fail; } - nb_ostreams += os->nb_streams; - } - - ost_table = av_mallocz(sizeof(OutputStream *) * nb_ostreams); - if (!ost_table) - goto fail; - - for(k=0;knb_streams;i++,n++) { - nb_streams[os->streams[i]->codec->codec_type]++; - } - } - for(step=1<<30; step; step>>=1){ - int found_streams[AVMEDIA_TYPE_NB]={0}; - for(j=0; jfile_index ].ctx; - skip=1; - for(pi=0; pinb_programs; pi++){ - AVProgram *p= f->programs[pi]; - if(p->id == opt_programid) - for(si=0; sinb_stream_indexes; si++){ - if(f->streams[ p->stream_index[si] ] == ist->st) - skip=0; - } - } - } - if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip - && nb_frame_threshold[ist->st->codec->codec_type] <= ist->st->codec_info_nb_frames){ - found_streams[ist->st->codec->codec_type]++; - } - } - for(j=0; jnb_streams; i++, n++) - ost_table[n] = output_streams_for_file[k][i]; } /* for each output stream, we compute the right encoding parameters */ - for(i=0;ifile_index]; + for (i = 0; i < nb_output_streams; i++) { + ost = &output_streams[i]; + os = output_files[ost->file_index].ctx; ist = &input_streams[ost->source_index]; codec = ost->st->codec; @@ -2176,8 +2160,8 @@ static int transcode(AVFormatContext **output_files, } /* open each encoder */ - for(i=0;iencoding_needed) { AVCodec *codec = ost->enc; AVCodecContext *dec = input_streams[ost->source_index].st->codec; @@ -2224,6 +2208,7 @@ static int transcode(AVFormatContext **output_files, ret = AVERROR(EINVAL); goto dump_format; } + if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) { snprintf(error, sizeof(error), "Error while opening decoder for input stream #%d.%d", ist->file_index, ist->st->index); @@ -2246,15 +2231,15 @@ static int transcode(AVFormatContext **output_files, } /* open files and write file headers */ - for(i=0;ioformat->name, "rtp")) { +// assert_avoptions(output_files[i].opts); + if (strcmp(os->oformat->name, "rtp")) { want_sdp = 0; } } @@ -2263,14 +2248,14 @@ static int transcode(AVFormatContext **output_files, /* dump the file output parameters - cannot be done before in case of stream copy */ for(i=0;ifilename, 1); + av_dump_format(output_files[i].ctx, i, output_files[i].ctx->filename, 1); } /* dump the stream mapping */ if (verbose >= 0) { fprintf(stderr, "Stream mapping:\n"); - for(i=0;i #%d.%d", input_streams[ost->source_index].file_index, input_streams[ost->source_index].st->index, @@ -2307,11 +2292,11 @@ static int transcode(AVFormatContext **output_files, for(; received_sigterm == 0;) { int file_index, ist_index; AVPacket pkt; - double ipts_min; + int64_t ipts_min; double opts_min; redo: - ipts_min= 1e100; + ipts_min = INT64_MAX; opts_min= 1e100; /* if 'q' pressed, exits */ if (!using_stdin) { @@ -2345,8 +2330,8 @@ static int transcode(AVFormatContext **output_files, for(i=0;icodec->debug = debug; } - for(i=0;ist->codec->debug = debug; } if(debug) av_log_set_level(AV_LOG_DEBUG); @@ -2368,15 +2353,16 @@ static int transcode(AVFormatContext **output_files, /* select the stream that we must read now by looking at the smallest output pts */ file_index = -1; - for(i=0;ifile_index]; + for (i = 0; i < nb_output_streams; i++) { + int64_t ipts; + double opts; + ost = &output_streams[i]; + os = output_files[ost->file_index].ctx; ist = &input_streams[ost->source_index]; - if(ist->is_past_recording_time || no_packet[ist->file_index]) + if(ost->is_past_recording_time || no_packet[ist->file_index]) continue; opts = ost->st->pts.val * av_q2d(ost->st->time_base); - ipts = (double)ist->pts; + ipts = ist->pts; if (!input_files[ist->file_index].eof_reached){ if(ipts < ipts_min) { ipts_min = ipts; @@ -2396,7 +2382,7 @@ static int transcode(AVFormatContext **output_files, if (file_index < 0) { if(no_packet_count){ no_packet_count=0; - memset(no_packet, 0, sizeof(no_packet)); + memset(no_packet, 0, nb_input_files); usleep(10000); continue; } @@ -2404,7 +2390,7 @@ static int transcode(AVFormatContext **output_files, } /* finish if limit size exhausted */ - if (limit_filesize != 0 && limit_filesize <= avio_tell(output_files[0]->pb)) + if (limit_filesize != 0 && limit_filesize <= avio_tell(output_files[0].ctx->pb)) break; /* read a frame from it and output it in the fifo */ @@ -2424,7 +2410,7 @@ static int transcode(AVFormatContext **output_files, } no_packet_count=0; - memset(no_packet, 0, sizeof(no_packet)); + memset(no_packet, 0, nb_input_files); if (do_pkt_dump) { av_pkt_dump_log2(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump, @@ -2467,19 +2453,8 @@ static int transcode(AVFormatContext **output_files, } } - /* finish if recording time exhausted */ - if (recording_time != INT64_MAX && - (pkt.pts != AV_NOPTS_VALUE ? - av_compare_ts(pkt.pts, ist->st->time_base, recording_time + start_time, (AVRational){1, 1000000}) - : - av_compare_ts(ist->pts, AV_TIME_BASE_Q, recording_time + start_time, (AVRational){1, 1000000}) - )>= 0) { - ist->is_past_recording_time = 1; - goto discard_packet; - } - //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size); - if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) { + if (output_packet(ist, ist_index, output_streams, nb_output_streams, &pkt) < 0) { if (verbose >= 0) fprintf(stderr, "Error while decoding stream #%d.%d\n", @@ -2494,14 +2469,14 @@ static int transcode(AVFormatContext **output_files, av_free_packet(&pkt); /* dump report by using the output first video and audio streams */ - print_report(output_files, ost_table, nb_ostreams, 0); + print_report(output_files, output_streams, nb_output_streams, 0); } /* at the end of stream, we must flush the decoder buffers */ for (i = 0; i < nb_input_streams; i++) { ist = &input_streams[i]; if (ist->decoding_needed) { - output_packet(ist, i, ost_table, nb_ostreams, NULL); + output_packet(ist, i, output_streams, nb_output_streams, NULL); } } @@ -2509,16 +2484,16 @@ static int transcode(AVFormatContext **output_files, /* write the trailer if needed and close file */ for(i=0;iencoding_needed) { av_freep(&ost->st->codec->stats_in); avcodec_close(ost->st->codec); @@ -2541,10 +2516,11 @@ static int transcode(AVFormatContext **output_files, fail: av_freep(&bit_buffer); + av_freep(&no_packet); - if (ost_table) { - for(i=0;ist->stream_copy) av_freep(&ost->st->codec->extradata); @@ -2564,10 +2540,8 @@ static int transcode(AVFormatContext **output_files, if (ost->reformat_ctx) av_audio_convert_free(ost->reformat_ctx); av_dict_free(&ost->opts); - av_free(ost); } } - av_free(ost_table); } return ret; } @@ -2911,21 +2885,7 @@ static int opt_map_metadata(const char *opt, const char *arg) static int opt_input_ts_scale(const char *opt, const char *arg) { - unsigned int stream; - double scale; - char *p; - - stream = strtol(arg, &p, 0); - if (*p) - p++; - scale= strtod(p, &p); - - if(stream >= MAX_STREAMS) - exit_program(1); - - ts_scale = grow_array(ts_scale, sizeof(*ts_scale), &nb_ts_scale, stream + 1); - ts_scale[stream] = scale; - return 0; + return av_dict_set(&ts_scale, opt, arg, 0); } static int opt_recording_time(const char *opt, const char *arg) @@ -2998,11 +2958,97 @@ static AVCodec *choose_codec(AVFormatContext *s, AVStream *st, enum AVMediaType return NULL; } +/** + * Add all the streams from the given input file to the global + * list of input streams. + */ +static void add_input_streams(AVFormatContext *ic) +{ + int i, rfps, rfps_base, ret; + + for (i = 0; i < ic->nb_streams; i++) { + AVStream *st = ic->streams[i]; + AVCodecContext *dec = st->codec; + AVDictionaryEntry *e = NULL; + InputStream *ist; + char *scale = NULL; + + dec->thread_count = thread_count; + + input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1); + ist = &input_streams[nb_input_streams - 1]; + ist->st = st; + ist->file_index = nb_input_files; + ist->discard = 1; + ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st); + + while (e = av_dict_get(ts_scale, "", e, AV_DICT_IGNORE_SUFFIX)) { + char *p = strchr(e->key, ':'); + + if ((ret = check_stream_specifier(ic, st, p ? p + 1 : "")) > 0) + scale = e->value; + else if (ret < 0) + exit_program(1); + } + if (scale) + ist->ts_scale = strtod(scale, NULL); + + ist->dec = choose_codec(ic, st, dec->codec_type, codec_names); + + switch (dec->codec_type) { + case AVMEDIA_TYPE_AUDIO: + if(!ist->dec) + ist->dec = avcodec_find_decoder(dec->codec_id); + if(audio_disable) + st->discard= AVDISCARD_ALL; + break; + case AVMEDIA_TYPE_VIDEO: + if(!ist->dec) + ist->dec = avcodec_find_decoder(dec->codec_id); + rfps = ic->streams[i]->r_frame_rate.num; + rfps_base = ic->streams[i]->r_frame_rate.den; + if (dec->lowres) { + dec->flags |= CODEC_FLAG_EMU_EDGE; + } + if(me_threshold) + dec->debug |= FF_DEBUG_MV; + + if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) { + + if (verbose >= 0) + fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n", + i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num, + + (float)rfps / rfps_base, rfps, rfps_base); + } + + if(video_disable) + st->discard= AVDISCARD_ALL; + else if(video_discard) + st->discard= video_discard; + break; + case AVMEDIA_TYPE_DATA: + break; + case AVMEDIA_TYPE_SUBTITLE: + if(!ist->dec) + ist->dec = avcodec_find_decoder(dec->codec_id); + if(subtitle_disable) + st->discard = AVDISCARD_ALL; + break; + case AVMEDIA_TYPE_ATTACHMENT: + case AVMEDIA_TYPE_UNKNOWN: + break; + default: + abort(); + } + } +} + static int opt_input_file(const char *opt, const char *filename) { AVFormatContext *ic; AVInputFormat *file_iformat = NULL; - int err, i, ret, rfps, rfps_base; + int err, i, ret; int64_t timestamp; uint8_t buf[128]; AVDictionary **opts; @@ -3115,72 +3161,7 @@ static int opt_input_file(const char *opt, const char *filename) } /* update the current parameters so that they match the one of the input stream */ - for(i=0;inb_streams;i++) { - AVStream *st = ic->streams[i]; - AVCodecContext *dec = st->codec; - InputStream *ist; - - dec->thread_count = thread_count; - - input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1); - ist = &input_streams[nb_input_streams - 1]; - ist->st = st; - ist->file_index = nb_input_files; - ist->discard = 1; - ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st); - - if (i < nb_ts_scale) - ist->ts_scale = ts_scale[i]; - - ist->dec = choose_codec(ic, st, dec->codec_type, codec_names); - - switch (dec->codec_type) { - case AVMEDIA_TYPE_AUDIO: - if(!ist->dec) - ist->dec = avcodec_find_decoder(dec->codec_id); - if(audio_disable) - st->discard= AVDISCARD_ALL; - break; - case AVMEDIA_TYPE_VIDEO: - if(!ist->dec) - ist->dec = avcodec_find_decoder(dec->codec_id); - rfps = ic->streams[i]->r_frame_rate.num; - rfps_base = ic->streams[i]->r_frame_rate.den; - if (dec->lowres) { - dec->flags |= CODEC_FLAG_EMU_EDGE; - } - if(me_threshold) - dec->debug |= FF_DEBUG_MV; - - if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) { - - if (verbose >= 0) - fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n", - i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num, - - (float)rfps / rfps_base, rfps, rfps_base); - } - - if(video_disable) - st->discard= AVDISCARD_ALL; - else if(video_discard) - st->discard= video_discard; - break; - case AVMEDIA_TYPE_DATA: - break; - case AVMEDIA_TYPE_SUBTITLE: - if(!ist->dec) - ist->dec = avcodec_find_decoder(dec->codec_id); - if(subtitle_disable) - st->discard = AVDISCARD_ALL; - break; - case AVMEDIA_TYPE_ATTACHMENT: - case AVMEDIA_TYPE_UNKNOWN: - break; - default: - abort(); - } - } + add_input_streams(ic); /* dump the file content */ if (verbose >= 0) @@ -3200,8 +3181,7 @@ static int opt_input_file(const char *opt, const char *filename) audio_sample_rate = 0; audio_channels = 0; audio_sample_fmt = AV_SAMPLE_FMT_NONE; - av_freep(&ts_scale); - nb_ts_scale = 0; + av_dict_free(&ts_scale); for (i = 0; i < orig_nb_streams; i++) av_dict_free(&opts[i]); @@ -3246,17 +3226,9 @@ static OutputStream *new_output_stream(AVFormatContext *oc, enum AVMediaType typ exit_program(1); } - output_streams_for_file[nb_output_files] = - grow_array(output_streams_for_file[nb_output_files], - sizeof(*output_streams_for_file[nb_output_files]), - &nb_output_streams_for_file[nb_output_files], - oc->nb_streams); - ost = output_streams_for_file[nb_output_files][idx] = - av_mallocz(sizeof(OutputStream)); - if (!ost) { - fprintf(stderr, "Could not alloc output stream\n"); - exit_program(1); - } + output_streams = grow_array(output_streams, sizeof(*output_streams), &nb_output_streams, + nb_output_streams + 1); + ost = &output_streams[nb_output_streams - 1]; ost->file_index = nb_output_files; ost->index = idx; ost->st = st; @@ -3516,7 +3488,7 @@ static int opt_streamid(const char *opt, const char *arg) static int copy_chapters(int infile, int outfile) { AVFormatContext *is = input_files[infile].ctx; - AVFormatContext *os = output_files[outfile]; + AVFormatContext *os = output_files[outfile].ctx; int i; for (i = 0; i < is->nb_chapters; i++) { @@ -3595,11 +3567,6 @@ static int opt_output_file(const char *opt, const char *filename) OutputStream *ost; InputStream *ist; - if(nb_output_files >= FF_ARRAY_ELEMS(output_files)){ - fprintf(stderr, "Too many output files\n"); - exit_program(1); - } - if (!strcmp(filename, "-")) filename = "pipe:"; @@ -3697,8 +3664,13 @@ static int opt_output_file(const char *opt, const char *filename) av_dict_copy(&oc->metadata, metadata, 0); av_dict_free(&metadata); - av_dict_copy(&output_opts[nb_output_files], format_opts, 0); - output_files[nb_output_files++] = oc; + + output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1); + output_files[nb_output_files - 1].ctx = oc; + output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams; + output_files[nb_output_files - 1].recording_time = recording_time; + output_files[nb_output_files - 1].start_time = start_time; + av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0); /* check filename in case of an image number is expected */ if (oc->oformat->flags & AVFMT_NEEDNUMBER) { @@ -3810,9 +3782,9 @@ static int opt_output_file(const char *opt, const char *filename) av_dict_copy(&oc->metadata, input_files[0].ctx->metadata, AV_DICT_DONT_OVERWRITE); if (metadata_streams_autocopy) - for (i = 0; i < oc->nb_streams; i++) { - InputStream *ist = &input_streams[output_streams_for_file[nb_output_files-1][i]->source_index]; - av_dict_copy(&oc->streams[i]->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); + for (i = output_files[nb_output_files - 1].ost_index; i < nb_output_streams; i++) { + InputStream *ist = &input_streams[output_streams[i].source_index]; + av_dict_copy(&output_streams[i].st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); } frame_rate = (AVRational){0, 0}; @@ -3822,6 +3794,8 @@ static int opt_output_file(const char *opt, const char *filename) audio_channels = 0; audio_sample_fmt = AV_SAMPLE_FMT_NONE; chapters_input_file = INT_MAX; + recording_time = INT64_MAX; + start_time = 0; av_freep(&meta_data_maps); nb_meta_data_maps = 0; @@ -4203,7 +4177,7 @@ static const OptionDef options[] = { { "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, // { "ss", HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" }, { "itsoffset", HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" }, - { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "stream:scale" }, + { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "scale" }, { "metadata", HAS_ARG, {(void*)opt_metadata}, "add metadata", "string=string" }, { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[AVMEDIA_TYPE_DATA]}, "set the number of data frames to record", "number" }, { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark}, diff --git a/doc/general.texi b/doc/general.texi index c5045b1095..1708e1b29f 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -260,6 +260,8 @@ library: @tab Multimedia format used in Westwood Studios games. @item Westwood Studios VQA @tab @tab X @tab Multimedia format used in Westwood Studios games. +@item XMV @tab @tab X + @tab Microsoft video container used in Xbox games. @item xWMA @tab @tab X @tab Microsoft audio container used by XAudio 2. @item YUV4MPEG pipe @tab X @tab X diff --git a/ffmpeg.c b/ffmpeg.c index e895b787aa..8e2c29fe14 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -736,7 +736,6 @@ static int read_ffserver_streams(AVFormatContext *s, const char *filename) { int i, err; AVFormatContext *ic = NULL; - int nopts = 0; err = avformat_open_input(&ic, filename, NULL, NULL); if (err < 0) @@ -768,9 +767,6 @@ static int read_ffserver_streams(AVFormatContext *s, const char *filename) } else choose_pixel_fmt(st, codec); } - - if(st->codec->flags & CODEC_FLAG_BITEXACT) - nopts = 1; } av_close_input_file(ic); @@ -1725,6 +1721,14 @@ static int output_packet(InputStream *ist, int ist_index, int frame_size; ost = ost_table[i]; + + /* finish if recording time exhausted */ + if (recording_time != INT64_MAX && + av_compare_ts(ist->pts, AV_TIME_BASE_Q, recording_time + start_time, (AVRational){1, 1000000}) + >= 0) { + ist->is_past_recording_time = 1; + continue; + } if (ost->source_index == ist_index) { #if CONFIG_AVFILTER frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || @@ -2804,17 +2808,6 @@ static int transcode(AVFormatContext **output_files, } } - /* finish if recording time exhausted */ - if (recording_time != INT64_MAX && - (pkt.pts != AV_NOPTS_VALUE ? - av_compare_ts(pkt.pts, ist->st->time_base, recording_time + start_time, (AVRational){1, 1000000}) - : - av_compare_ts(ist->pts, AV_TIME_BASE_Q, recording_time + start_time, (AVRational){1, 1000000}) - )>= 0) { - ist->is_past_recording_time = 1; - goto discard_packet; - } - //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size); if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) { diff --git a/libavcodec/Makefile b/libavcodec/Makefile index e0e19a21a1..147c1b3587 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -635,6 +635,8 @@ OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \ mpeg12.o mpeg12data.o \ mpegvideo.o error_resilience.o OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o +OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o +OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \ msmpeg4.o msmpeg4data.o mpeg4video.o \ h263.o mpegvideo.o error_resilience.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 89955017e0..8ca6181e45 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -409,6 +409,8 @@ void avcodec_register_all(void) REGISTER_PARSER (MPEGAUDIO, mpegaudio); REGISTER_PARSER (MPEGVIDEO, mpegvideo); REGISTER_PARSER (PNM, pnm); + REGISTER_PARSER (RV30, rv30); + REGISTER_PARSER (RV40, rv40); REGISTER_PARSER (VC1, vc1); REGISTER_PARSER (VP3, vp3); REGISTER_PARSER (VP8, vp8); diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c index 3a59d5f477..0f91020a2d 100644 --- a/libavcodec/h264_refs.c +++ b/libavcodec/h264_refs.c @@ -655,7 +655,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ print_short_term(h); print_long_term(h); - return err; + return h->s.avctx->error_recognition >= FF_ER_EXPLODE ? err : 0; } int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb){ diff --git a/libavcodec/rv34_parser.c b/libavcodec/rv34_parser.c new file mode 100644 index 0000000000..ce8604345e --- /dev/null +++ b/libavcodec/rv34_parser.c @@ -0,0 +1,95 @@ +/* + * RV30/40 parser + * Copyright (c) 2011 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * RV30/40 parser + */ + +#include "parser.h" +#include "libavutil/intreadwrite.h" + +typedef struct { + ParseContext pc; + int64_t key_dts; + int key_pts; +} RV34ParseContext; + +static const int rv_to_av_frame_type[4] = { + AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, +}; + +static int rv34_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + RV34ParseContext *pc = s->priv_data; + int type, pts, hdr; + + if (buf_size < 13 + *buf * 8) { + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; + } + + hdr = AV_RB32(buf + 9 + *buf * 8); + if (avctx->codec_id == CODEC_ID_RV30) { + type = (hdr >> 27) & 3; + pts = (hdr >> 7) & 0x1FFF; + } else { + type = (hdr >> 29) & 3; + pts = (hdr >> 6) & 0x1FFF; + } + + if (type != 3 && s->pts != AV_NOPTS_VALUE) { + pc->key_dts = s->pts; + pc->key_pts = pts; + } else { + if (type != 3) + s->pts = pc->key_dts + ((pts - pc->key_pts) & 0x1FFF); + else + s->pts = pc->key_dts - ((pc->key_pts - pts) & 0x1FFF); + } + s->pict_type = rv_to_av_frame_type[type]; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; +} + +#ifdef CONFIG_RV30_PARSER +AVCodecParser ff_rv30_parser = { + { CODEC_ID_RV30 }, + sizeof(RV34ParseContext), + NULL, + rv34_parse, +}; +#endif + +#ifdef CONFIG_RV40_PARSER +AVCodecParser ff_rv40_parser = { + { CODEC_ID_RV40 }, + sizeof(RV34ParseContext), + NULL, + rv34_parse, +}; +#endif diff --git a/libavcodec/x86/dsputil_yasm.asm b/libavcodec/x86/dsputil_yasm.asm index 1f5a4f68c7..794b549a79 100644 --- a/libavcodec/x86/dsputil_yasm.asm +++ b/libavcodec/x86/dsputil_yasm.asm @@ -20,6 +20,7 @@ ;****************************************************************************** %include "x86inc.asm" +%include "x86util.asm" SECTION_RODATA pb_f: times 16 db 15 @@ -1054,39 +1055,6 @@ emu_edge mmx ; int32_t max, unsigned int len) ;----------------------------------------------------------------------------- -%macro PMINSD_MMX 3 ; dst, src, tmp - mova %3, %2 - pcmpgtd %3, %1 - pxor %1, %2 - pand %1, %3 - pxor %1, %2 -%endmacro - -%macro PMAXSD_MMX 3 ; dst, src, tmp - mova %3, %1 - pcmpgtd %3, %2 - pand %1, %3 - pandn %3, %2 - por %1, %3 -%endmacro - -%macro CLIPD_MMX 3-4 ; src/dst, min, max, tmp - PMINSD_MMX %1, %3, %4 - PMAXSD_MMX %1, %2, %4 -%endmacro - -%macro CLIPD_SSE2 3-4 ; src/dst, min (float), max (float), unused - cvtdq2ps %1, %1 - minps %1, %3 - maxps %1, %2 - cvtps2dq %1, %1 -%endmacro - -%macro CLIPD_SSE41 3-4 ; src/dst, min, max, unused - pminsd %1, %3 - pmaxsd %1, %2 -%endmacro - %macro SPLATD_MMX 1 punpckldq %1, %1 %endmacro diff --git a/libavformat/Makefile b/libavformat/Makefile index 9f5bfb42ad..d597c624a9 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -305,6 +305,7 @@ OBJS-$(CONFIG_WTV_DEMUXER) += wtvdec.o wtv.o asfdec.o asf.o asfcry avlanguage.o mpegts.o isom.o riff.o OBJS-$(CONFIG_WV_DEMUXER) += wv.o apetag.o OBJS-$(CONFIG_XA_DEMUXER) += xa.o +OBJS-$(CONFIG_XMV_DEMUXER) += xmv.o OBJS-$(CONFIG_XWMA_DEMUXER) += xwma.o riff.o OBJS-$(CONFIG_YOP_DEMUXER) += yop.o OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index a9fa117243..c64c355523 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -227,6 +227,7 @@ void av_register_all(void) REGISTER_DEMUXER (WTV, wtv); REGISTER_DEMUXER (WV, wv); REGISTER_DEMUXER (XA, xa); + REGISTER_DEMUXER (XMV, xmv); REGISTER_DEMUXER (XWMA, xwma); REGISTER_DEMUXER (YOP, yop); REGISTER_MUXDEMUX (YUV4MPEGPIPE, yuv4mpegpipe); diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index 461c45c81c..7f25af7994 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -293,20 +293,21 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb, // av_log(s, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0')); if (st->codec->codec_id == CODEC_ID_NONE) goto fail1; - st->codec->width = avio_rb16(pb); + st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); - st->codec->time_base.num= 1; - fps= avio_rb16(pb); + avio_skip(pb, 2); // looks like bits per sample + avio_skip(pb, 4); // always zero? st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - avio_rb32(pb); - avio_skip(pb, 2); - avio_rb16(pb); + st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; + fps = avio_rb32(pb); if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (avio_tell(pb) - codec_pos))) < 0) return ret; -// av_log(s, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2); - st->codec->time_base.den = fps * st->codec->time_base.num; + av_reduce(&st->codec->time_base.num, &st->codec->time_base.den, + 0x10000, fps, (1 << 30) - 1); + st->avg_frame_rate.num = st->codec->time_base.den; + st->avg_frame_rate.den = st->codec->time_base.num; } skip: @@ -570,7 +571,8 @@ skip: static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, RMDemuxContext *rm, RMStream *vst, - AVPacket *pkt, int len, int *pseq) + AVPacket *pkt, int len, int *pseq, + int64_t *timestamp) { int hdr, seq, pic_num, len2, pos; int type; @@ -590,8 +592,10 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, return -1; rm->remaining_len = len; if(type&1){ // frame, not slice - if(type == 3) // frame as a part of packet + if(type == 3){ // frame as a part of packet len= len2; + *timestamp = pos; + } if(rm->remaining_len < len) return -1; rm->remaining_len -= len; @@ -699,7 +703,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { rm->current_stream= st->id; - if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq)) + if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, ×tamp)) return -1; //got partial frame } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { if ((st->codec->codec_id == CODEC_ID_RA_288) || @@ -774,7 +778,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, } #endif - pkt->pts= timestamp; + pkt->pts = timestamp; if (flags & 2) pkt->flags |= AV_PKT_FLAG_KEY; diff --git a/libavformat/version.h b/libavformat/version.h index 5b6031b3ec..f811c31e9b 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -24,7 +24,7 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 53 -#define LIBAVFORMAT_VERSION_MINOR 7 +#define LIBAVFORMAT_VERSION_MINOR 8 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/xmv.c b/libavformat/xmv.c new file mode 100644 index 0000000000..a6081aff7b --- /dev/null +++ b/libavformat/xmv.c @@ -0,0 +1,576 @@ +/* + * Microsoft XMV demuxer + * Copyright (c) 2011 Sven Hesse + * Copyright (c) 2011 Matthew Hoops + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Microsoft XMV demuxer + */ + +#include + +#include "libavutil/intreadwrite.h" + +#include "avformat.h" +#include "riff.h" + +#define XMV_MIN_HEADER_SIZE 36 + +#define XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT 1 +#define XMV_AUDIO_ADPCM51_FRONTCENTERLOW 2 +#define XMV_AUDIO_ADPCM51_REARLEFTRIGHT 4 + +#define XMV_AUDIO_ADPCM51 (XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT | \ + XMV_AUDIO_ADPCM51_FRONTCENTERLOW | \ + XMV_AUDIO_ADPCM51_REARLEFTRIGHT) + +typedef struct XMVAudioTrack { + uint16_t compression; + uint16_t channels; + uint32_t sample_rate; + uint16_t bits_per_sample; + uint32_t bit_rate; + uint16_t flags; + uint16_t block_align; + uint16_t block_samples; + + enum CodecID codec_id; +} XMVAudioTrack; + +typedef struct XMVVideoPacket { + /* The decoder stream index for this video packet. */ + int stream_index; + + uint32_t data_size; + uint32_t data_offset; + + uint32_t current_frame; + uint32_t frame_count; + + /* Does the video packet contain extra data? */ + int has_extradata; + + /* Extra data */ + uint8_t extradata[4]; + + int64_t last_pts; + int64_t pts; +} XMVVideoPacket; + +typedef struct XMVAudioPacket { + /* The decoder stream index for this audio packet. */ + int stream_index; + + /* The audio track this packet encodes. */ + XMVAudioTrack *track; + + uint32_t data_size; + uint32_t data_offset; + + uint32_t frame_size; + + uint32_t block_count; +} XMVAudioPacket; + +typedef struct XMVDemuxContext { + uint16_t audio_track_count; + + XMVAudioTrack *audio_tracks; + + uint32_t this_packet_size; + uint32_t next_packet_size; + + uint32_t this_packet_offset; + uint32_t next_packet_offset; + + uint16_t current_stream; + uint16_t stream_count; + + XMVVideoPacket video; + XMVAudioPacket *audio; +} XMVDemuxContext; + +static int xmv_probe(AVProbeData *p) +{ + uint32_t file_version; + + if (p->buf_size < XMV_MIN_HEADER_SIZE) + return 0; + + file_version = AV_RL32(p->buf + 16); + if ((file_version == 0) || (file_version > 4)) + return 0; + + if (!memcmp(p->buf + 12, "xobX", 4)) + return AVPROBE_SCORE_MAX; + + return 0; +} + +static int xmv_read_header(AVFormatContext *s, + AVFormatParameters *ap) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *vst = NULL; + + uint32_t file_version; + uint32_t this_packet_size; + uint16_t audio_track; + + avio_skip(pb, 4); /* Next packet size */ + + this_packet_size = avio_rl32(pb); + + avio_skip(pb, 4); /* Max packet size */ + avio_skip(pb, 4); /* "xobX" */ + + file_version = avio_rl32(pb); + if ((file_version != 4) && (file_version != 2)) + av_log_ask_for_sample(s, "Found uncommon version %d\n", file_version); + + + /* Video track */ + + vst = av_new_stream(s, 0); + if (!vst) + return AVERROR(ENOMEM); + + av_set_pts_info(vst, 32, 1, 1000); + + vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codec->codec_id = CODEC_ID_WMV2; + vst->codec->codec_tag = MKBETAG('W', 'M', 'V', '2'); + vst->codec->width = avio_rl32(pb); + vst->codec->height = avio_rl32(pb); + + vst->duration = avio_rl32(pb); + + xmv->video.stream_index = vst->index; + + /* Audio tracks */ + + xmv->audio_track_count = avio_rl16(pb); + + avio_skip(pb, 2); /* Unknown (padding?) */ + + xmv->audio_tracks = av_malloc(xmv->audio_track_count * sizeof(XMVAudioTrack)); + if (!xmv->audio_tracks) + return AVERROR(ENOMEM); + + xmv->audio = av_malloc(xmv->audio_track_count * sizeof(XMVAudioPacket)); + if (!xmv->audio) + return AVERROR(ENOMEM); + + for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) { + XMVAudioTrack *track = &xmv->audio_tracks[audio_track]; + XMVAudioPacket *packet = &xmv->audio [audio_track]; + AVStream *ast = NULL; + + track->compression = avio_rl16(pb); + track->channels = avio_rl16(pb); + track->sample_rate = avio_rl32(pb); + track->bits_per_sample = avio_rl16(pb); + track->flags = avio_rl16(pb); + + track->bit_rate = track->bits_per_sample * + track->sample_rate * + track->channels; + track->block_align = 36 * track->channels; + track->block_samples = 64; + track->codec_id = ff_wav_codec_get_id(track->compression, + track->bits_per_sample); + + packet->track = track; + packet->stream_index = -1; + + packet->frame_size = 0; + packet->block_count = 0; + + /* TODO: ADPCM'd 5.1 sound is encoded in three separate streams. + * Those need to be interleaved to a proper 5.1 stream. */ + if (track->flags & XMV_AUDIO_ADPCM51) + av_log(s, AV_LOG_WARNING, "Unsupported 5.1 ADPCM audio stream " + "(0x%04X)\n", track->flags); + + ast = av_new_stream(s, audio_track); + if (!ast) + return AVERROR(ENOMEM); + + ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codec->codec_id = track->codec_id; + ast->codec->codec_tag = track->compression; + ast->codec->channels = track->channels; + ast->codec->sample_rate = track->sample_rate; + ast->codec->bits_per_coded_sample = track->bits_per_sample; + ast->codec->bit_rate = track->bit_rate; + ast->codec->block_align = 36 * track->channels; + + av_set_pts_info(ast, 32, track->block_samples, track->sample_rate); + + packet->stream_index = ast->index; + + ast->duration = vst->duration; + } + + + /** Initialize the packet context */ + + xmv->next_packet_offset = avio_tell(pb); + + xmv->next_packet_size = this_packet_size - xmv->next_packet_offset; + xmv->this_packet_size = 0; + + xmv->video.current_frame = 0; + xmv->video.frame_count = 0; + xmv->video.pts = 0; + xmv->video.last_pts = 0; + + xmv->current_stream = 0; + xmv->stream_count = xmv->audio_track_count + 1; + + return 0; +} + +static void xmv_read_extradata(uint8_t *extradata, AVIOContext *pb) +{ + /* Read the XMV extradata */ + + uint32_t data = avio_rl32(pb); + + int mspel_bit = !!(data & 0x01); + int loop_filter = !!(data & 0x02); + int abt_flag = !!(data & 0x04); + int j_type_bit = !!(data & 0x08); + int top_left_mv_flag = !!(data & 0x10); + int per_mb_rl_bit = !!(data & 0x20); + int slice_count = (data >> 6) & 7; + + /* Write it back as standard WMV2 extradata */ + + data = 0; + + data |= mspel_bit << 15; + data |= loop_filter << 14; + data |= abt_flag << 13; + data |= j_type_bit << 12; + data |= top_left_mv_flag << 11; + data |= per_mb_rl_bit << 10; + data |= slice_count << 7; + + AV_WB32(extradata, data); +} + +static int xmv_process_packet_header(AVFormatContext *s) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + + uint8_t data[8]; + uint16_t audio_track; + uint32_t data_offset; + + /* Next packet size */ + xmv->next_packet_size = avio_rl32(pb); + + /* Packet video header */ + + if (avio_read(pb, data, 8) != 8) + return AVERROR(EIO); + + xmv->video.data_size = AV_RL32(data) & 0x007FFFFF; + + xmv->video.current_frame = 0; + xmv->video.frame_count = (AV_RL32(data) >> 23) & 0xFF; + + xmv->video.has_extradata = (data[3] & 0x80) != 0; + + /* Adding the audio data sizes and the video data size keeps you 4 bytes + * short for every audio track. But as playing around with XMV files with + * ADPCM audio showed, taking the extra 4 bytes from the audio data gives + * you either completely distorted audio or click (when skipping the + * remaining 68 bytes of the ADPCM block). Substracting 4 bytes for every + * audio track from the video data works at least for the audio. Probably + * some alignment thing? + * The video data has (always?) lots of padding, so it should work out... + */ + xmv->video.data_size -= xmv->audio_track_count * 4; + + xmv->current_stream = 0; + if (!xmv->video.frame_count) { + xmv->video.frame_count = 1; + xmv->current_stream = 1; + } + + /* Packet audio header */ + + for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) { + XMVAudioPacket *packet = &xmv->audio[audio_track]; + + if (avio_read(pb, data, 4) != 4) + return AVERROR(EIO); + + packet->data_size = AV_RL32(data) & 0x007FFFFF; + if ((packet->data_size == 0) && (audio_track != 0)) + /* This happens when I create an XMV with several identical audio + * streams. From the size calculations, duplicating the previous + * stream's size works out, but the track data itself is silent. + * Maybe this should also redirect the offset to the previous track? + */ + packet->data_size = xmv->audio[audio_track - 1].data_size; + + /** Carve up the audio data in frame_count slices */ + packet->frame_size = packet->data_size / xmv->video.frame_count; + packet->frame_size -= packet->frame_size % packet->track->block_align; + } + + /* Packet data offsets */ + + data_offset = avio_tell(pb); + + xmv->video.data_offset = data_offset; + data_offset += xmv->video.data_size; + + for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) { + xmv->audio[audio_track].data_offset = data_offset; + data_offset += xmv->audio[audio_track].data_size; + } + + /* Video frames header */ + + /* Read new video extra data */ + if (xmv->video.data_size > 0) { + if (xmv->video.has_extradata) { + xmv_read_extradata(xmv->video.extradata, pb); + + xmv->video.data_size -= 4; + xmv->video.data_offset += 4; + + if (xmv->video.stream_index >= 0) { + AVStream *vst = s->streams[xmv->video.stream_index]; + + assert(xmv->video.stream_index < s->nb_streams); + + if (vst->codec->extradata_size < 4) { + av_free(vst->codec->extradata); + + vst->codec->extradata = + av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE); + vst->codec->extradata_size = 4; + } + + memcpy(vst->codec->extradata, xmv->video.extradata, 4); + } + } + } + + return 0; +} + +static int xmv_fetch_new_packet(AVFormatContext *s) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + int result; + + /* Seek to it */ + xmv->this_packet_offset = xmv->next_packet_offset; + if (avio_seek(pb, xmv->this_packet_offset, SEEK_SET) != xmv->this_packet_offset) + return AVERROR(EIO); + + /* Update the size */ + xmv->this_packet_size = xmv->next_packet_size; + if (xmv->this_packet_size < (12 + xmv->audio_track_count * 4)) + return AVERROR(EIO); + + /* Process the header */ + result = xmv_process_packet_header(s); + if (result) + return result; + + /* Update the offset */ + xmv->next_packet_offset = xmv->this_packet_offset + xmv->this_packet_size; + + return 0; +} + +static int xmv_fetch_audio_packet(AVFormatContext *s, + AVPacket *pkt, uint32_t stream) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + XMVAudioPacket *audio = &xmv->audio[stream]; + + uint32_t data_size; + uint32_t block_count; + int result; + + /* Seek to it */ + if (avio_seek(pb, audio->data_offset, SEEK_SET) != audio->data_offset) + return AVERROR(EIO); + + if ((xmv->video.current_frame + 1) < xmv->video.frame_count) + /* Not the last frame, get at most frame_size bytes. */ + data_size = FFMIN(audio->frame_size, audio->data_size); + else + /* Last frame, get the rest. */ + data_size = audio->data_size; + + /* Read the packet */ + result = av_get_packet(pb, pkt, data_size); + if (result <= 0) + return result; + + pkt->stream_index = audio->stream_index; + + /* Calculate the PTS */ + + block_count = data_size / audio->track->block_align; + + pkt->duration = block_count; + pkt->pts = audio->block_count; + pkt->dts = AV_NOPTS_VALUE; + + audio->block_count += block_count; + + /* Advance offset */ + audio->data_size -= data_size; + audio->data_offset += data_size; + + return 0; +} + +static int xmv_fetch_video_packet(AVFormatContext *s, + AVPacket *pkt) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + XMVVideoPacket *video = &xmv->video; + + int result; + uint32_t frame_header; + uint32_t frame_size, frame_timestamp; + uint32_t i; + + /* Seek to it */ + if (avio_seek(pb, video->data_offset, SEEK_SET) != video->data_offset) + return AVERROR(EIO); + + /* Read the frame header */ + frame_header = avio_rl32(pb); + + frame_size = (frame_header & 0x1FFFF) * 4 + 4; + frame_timestamp = (frame_header >> 17); + + if ((frame_size + 4) > video->data_size) + return AVERROR(EIO); + + /* Create the packet */ + result = av_new_packet(pkt, frame_size); + if (result) + return result; + + /* Contrary to normal WMV2 video, the bit stream in XMV's + * WMV2 is little-endian. + * TODO: This manual swap is of course suboptimal. + */ + for (i = 0; i < frame_size; i += 4) + AV_WB32(pkt->data + i, avio_rl32(pb)); + + pkt->stream_index = video->stream_index; + + /* Calculate the PTS */ + + video->last_pts = frame_timestamp + video->pts; + + pkt->duration = 0; + pkt->pts = video->last_pts; + pkt->dts = AV_NOPTS_VALUE; + + video->pts += frame_timestamp; + + /* Keyframe? */ + pkt->flags = (pkt->data[0] & 0x80) ? 0 : AV_PKT_FLAG_KEY; + + /* Advance offset */ + video->data_size -= frame_size + 4; + video->data_offset += frame_size + 4; + + return 0; +} + +static int xmv_read_packet(AVFormatContext *s, + AVPacket *pkt) +{ + XMVDemuxContext *xmv = s->priv_data; + int result; + + if (xmv->video.current_frame == xmv->video.frame_count) { + /* No frames left in this packet, so we fetch a new one */ + + result = xmv_fetch_new_packet(s); + if (result) + return result; + } + + if (xmv->current_stream == 0) { + /* Fetch a video frame */ + + result = xmv_fetch_video_packet(s, pkt); + if (result) + return result; + + } else { + /* Fetch an audio frame */ + + result = xmv_fetch_audio_packet(s, pkt, xmv->current_stream - 1); + if (result) + return result; + } + + /* Increase our counters */ + if (++xmv->current_stream >= xmv->stream_count) { + xmv->current_stream = 0; + xmv->video.current_frame += 1; + } + + return 0; +} + +static int xmv_read_close(AVFormatContext *s) +{ + XMVDemuxContext *xmv = s->priv_data; + + av_free(xmv->audio); + av_free(xmv->audio_tracks); + + return 0; +} + +AVInputFormat ff_xmv_demuxer = { + .name = "xmv", + .long_name = NULL_IF_CONFIG_SMALL("Microsoft XMV"), + .priv_data_size = sizeof(XMVDemuxContext), + .read_probe = xmv_probe, + .read_header = xmv_read_header, + .read_packet = xmv_read_packet, + .read_close = xmv_read_close, +}; diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm index 1cede4d336..fc4781b532 100644 --- a/libavutil/x86/x86util.asm +++ b/libavutil/x86/x86util.asm @@ -540,3 +540,36 @@ pmaxsw %1, %2 pminsw %1, %3 %endmacro + +%macro PMINSD_MMX 3 ; dst, src, tmp + mova %3, %2 + pcmpgtd %3, %1 + pxor %1, %2 + pand %1, %3 + pxor %1, %2 +%endmacro + +%macro PMAXSD_MMX 3 ; dst, src, tmp + mova %3, %1 + pcmpgtd %3, %2 + pand %1, %3 + pandn %3, %2 + por %1, %3 +%endmacro + +%macro CLIPD_MMX 3-4 ; src/dst, min, max, tmp + PMINSD_MMX %1, %3, %4 + PMAXSD_MMX %1, %2, %4 +%endmacro + +%macro CLIPD_SSE2 3-4 ; src/dst, min (float), max (float), unused + cvtdq2ps %1, %1 + minps %1, %3 + maxps %1, %2 + cvtps2dq %1, %1 +%endmacro + +%macro CLIPD_SSE41 3-4 ; src/dst, min, max, unused + pminsd %1, %3 + pmaxsd %1, %2 +%endmacro diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c index 8a5bac308e..439aa91461 100644 --- a/libswscale/ppc/swscale_altivec.c +++ b/libswscale/ppc/swscale_altivec.c @@ -400,7 +400,7 @@ void ff_sws_init_swScale_altivec(SwsContext *c) return; if (c->srcBpc == 8 && c->dstBpc <= 10) { - c->hScale = hScale_altivec_real; + c->hyScale = c->hcScale = hScale_altivec_real; } if (!is16BPS(dstFormat) && !is9_OR_10BPS(dstFormat) && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 && diff --git a/libswscale/swscale.c b/libswscale/swscale.c index e94a6f7a7c..0f886486e8 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -2212,7 +2212,7 @@ static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth, int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1; c->hScale16(dst, dstWidth, (const uint16_t*)src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize, shift); } else if (!c->hyscale_fast) { - c->hScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize); + c->hyScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize); } else { // fast bilinear upscale / crap downscale c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc); } @@ -2258,8 +2258,8 @@ static av_always_inline void hcscale(SwsContext *c, int16_t *dst1, int16_t *dst2 c->hScale16(dst1, dstWidth, (const uint16_t*)src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift); c->hScale16(dst2, dstWidth, (const uint16_t*)src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift); } else if (!c->hcscale_fast) { - c->hScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize); - c->hScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize); + c->hcScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize); + c->hcScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize); } else { // fast bilinear upscale / crap downscale c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc); } @@ -2929,16 +2929,16 @@ static av_cold void sws_init_swScale_c(SwsContext *c) if (c->srcBpc == 8) { if (c->dstBpc <= 10) { - c->hScale = hScale8To15_c; + c->hyScale = c->hcScale = hScale8To15_c; if (c->flags & SWS_FAST_BILINEAR) { c->hyscale_fast = hyscale_fast_c; c->hcscale_fast = hcscale_fast_c; } } else { - c->hScale = hScale8To19_c; + c->hyScale = c->hcScale = hScale8To19_c; } } else { - c->hScale = c->dstBpc > 10 ? hScale16To19_c : hScale16To15_c; + c->hyScale = c->hcScale = c->dstBpc > 10 ? hScale16To19_c : hScale16To15_c; } if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) { diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index a936f96373..c572acb958 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -483,9 +483,14 @@ typedef struct SwsContext { * (and input coefficients thus padded with zeroes) * to simplify creating SIMD code. */ - void (*hScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, - const int16_t *filter, const int16_t *filterPos, - int filterSize); + /** @{ */ + void (*hyScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, + const int16_t *filter, const int16_t *filterPos, + int filterSize); + void (*hcScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, + const int16_t *filter, const int16_t *filterPos, + int filterSize); + /** @} */ void (*hScale16)(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc, const int16_t *filter, const int16_t *filterPos, diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c index 4163647fa0..7ba1901e21 100644 --- a/libswscale/x86/swscale_template.c +++ b/libswscale/x86/swscale_template.c @@ -2474,7 +2474,7 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c) if (c->srcBpc == 8 && c->dstBpc <= 10) { #if !COMPILE_TEMPLATE_MMX2 - c->hScale = RENAME(hScale ); + c->hyScale = c->hcScale = RENAME(hScale ); #endif /* !COMPILE_TEMPLATE_MMX2 */ // Use the new MMX scaler if the MMX2 one can't be used (it is faster than the x86 ASM one). diff --git a/tests/ref/fate/feeble-dxa b/tests/ref/fate/feeble-dxa index 9013f99118..caea4c2e2a 100644 --- a/tests/ref/fate/feeble-dxa +++ b/tests/ref/fate/feeble-dxa @@ -62,4 +62,3 @@ 0, 171000, 921600, 0x5639e670 1, 171429, 1000, 0xa491f3ef 1, 175510, 1000, 0x2c036e18 -1, 179592, 1000, 0x52d65e2a diff --git a/tests/ref/fate/lmlm4-demux b/tests/ref/fate/lmlm4-demux index 1d0d59f54d..f3214234d7 100644 --- a/tests/ref/fate/lmlm4-demux +++ b/tests/ref/fate/lmlm4-demux @@ -213,4 +213,3 @@ 1, 265680, 768, 0xfd6c7597 0, 267267, 1327, 0x7d15307c 1, 267840, 768, 0x8d766d40 -0, 270270, 1225, 0x1b5d0f5f diff --git a/tests/ref/fate/real-rv40 b/tests/ref/fate/real-rv40 index 990a530436..c63c525d08 100644 --- a/tests/ref/fate/real-rv40 +++ b/tests/ref/fate/real-rv40 @@ -1,121 +1,240 @@ 0, 0, 276480, 0x5f7a0d4f -0, 7500, 276480, 0x5f7a0d4f -0, 15000, 276480, 0x5f7a0d4f -0, 22500, 276480, 0x5f7a0d4f -0, 30000, 276480, 0x5f7a0d4f -0, 37500, 276480, 0x5f7a0d4f -0, 45000, 276480, 0x5f7a0d4f -0, 52500, 276480, 0x5f7a0d4f -0, 60000, 276480, 0x5f7a0d4f -0, 67500, 276480, 0x5f7a0d4f -0, 75000, 276480, 0x5f7a0d4f -0, 82500, 276480, 0x5f7a0d4f -0, 90000, 276480, 0x5f7a0d4f -0, 97500, 276480, 0x5f7a0d4f -0, 105000, 276480, 0x5f7a0d4f -0, 112500, 276480, 0x5f7a0d4f -0, 120000, 276480, 0x5f7a0d4f -0, 127500, 276480, 0x5f7a0d4f -0, 135000, 276480, 0x75641594 -0, 142500, 276480, 0x32ee3526 -0, 150000, 276480, 0x5ce39368 -0, 157500, 276480, 0x4ec1e418 -0, 165000, 276480, 0x85cbc3b5 -0, 172500, 276480, 0x377c7b46 -0, 180000, 276480, 0x756a4a2e -0, 187500, 276480, 0xcb379547 -0, 195000, 276480, 0x99c085be -0, 202500, 276480, 0xe479ffed -0, 210000, 276480, 0x1e4fae19 -0, 217500, 276480, 0x776412ef -0, 225000, 276480, 0x58ce0f38 -0, 232500, 276480, 0x5ab69b27 -0, 240000, 276480, 0xc3db9706 -0, 247500, 276480, 0xc9c57884 -0, 255000, 276480, 0x000b5269 -0, 262500, 276480, 0x27ff7a5d -0, 270000, 276480, 0x70647530 -0, 277500, 276480, 0x97612c4b -0, 285000, 276480, 0xdf4e04d7 -0, 292500, 276480, 0xbd98f57c -0, 300000, 276480, 0x5163b29b -0, 307500, 276480, 0x99170e64 -0, 315000, 276480, 0x8a4e991f -0, 322500, 276480, 0x6a45425f -0, 330000, 276480, 0x7bf6b1ef -0, 337500, 276480, 0x6de1e34b -0, 345000, 276480, 0xdcaaa99a -0, 352500, 276480, 0xd1e98808 -0, 360000, 276480, 0x6e2d524e -0, 367500, 276480, 0x22c50a3d -0, 375000, 276480, 0x62b76407 -0, 382500, 276480, 0x51e9b3eb -0, 390000, 276480, 0x441f7afd -0, 397500, 276480, 0xfb01efc6 -0, 405000, 276480, 0x294bb441 -0, 412500, 276480, 0xe04ac45e -0, 420000, 276480, 0x58f275ea -0, 427500, 276480, 0xf0b3b71b -0, 435000, 276480, 0x674e34e4 -0, 442500, 276480, 0x41dda2d9 -0, 450000, 276480, 0xf46ba7fb -0, 457500, 276480, 0x28b54815 -0, 465000, 276480, 0xaf2b5d89 -0, 472500, 276480, 0x8facba58 -0, 480000, 276480, 0x28a63236 -0, 487500, 276480, 0x1ad43fd7 -0, 495000, 276480, 0x71507bd2 -0, 502500, 276480, 0x35626022 -0, 510000, 276480, 0x7c1139b3 -0, 517500, 276480, 0x7fd73a99 -0, 525000, 276480, 0xb52e1aa2 -0, 532500, 276480, 0xd6f82cae -0, 540000, 276480, 0xf88f75d4 -0, 547500, 276480, 0x04a8e3ee -0, 555000, 276480, 0xa29f5b01 -0, 562500, 276480, 0x754ceaf5 -0, 570000, 276480, 0x5a38b4af -0, 577500, 276480, 0xfcebc261 -0, 585000, 276480, 0x3d3ca985 -0, 592500, 276480, 0x94a03c75 -0, 600000, 276480, 0x2f98911c -0, 607500, 276480, 0x923b9937 -0, 615000, 276480, 0xefab7ffd -0, 622500, 276480, 0x6b9fbc80 -0, 630000, 276480, 0xe4bdbd1e -0, 637500, 276480, 0x225a56c0 -0, 645000, 276480, 0xf58b1b7c -0, 652500, 276480, 0xbaffcdcc -0, 660000, 276480, 0xeb6eb88f -0, 667500, 276480, 0xdb753d35 -0, 675000, 276480, 0xea80a82e -0, 682500, 276480, 0x2aae902a -0, 690000, 276480, 0x9b9ee961 -0, 697500, 276480, 0xaa12b6fd -0, 705000, 276480, 0x50c31e73 -0, 712500, 276480, 0xdd9fb89f -0, 720000, 276480, 0xaf82399a -0, 727500, 276480, 0x7ce5f23c -0, 735000, 276480, 0x5aaa7519 -0, 742500, 276480, 0xe45a5599 -0, 750000, 276480, 0x704411fb -0, 757500, 276480, 0x9d7430a1 -0, 765000, 276480, 0x2c230702 -0, 772500, 276480, 0x4a4f76cd -0, 780000, 276480, 0x27f54854 -0, 787500, 276480, 0x694d76e3 -0, 795000, 276480, 0x525463e2 -0, 802500, 276480, 0x819898f9 -0, 810000, 276480, 0xeeed00fc -0, 817500, 276480, 0xb6f99ee3 -0, 825000, 276480, 0xefc83107 -0, 832500, 276480, 0xbb22e024 -0, 840000, 276480, 0x300f922a -0, 847500, 276480, 0x826fc3bd -0, 855000, 276480, 0x679a53f8 -0, 862500, 276480, 0x976c9e93 -0, 870000, 276480, 0xb194656e -0, 877500, 276480, 0xf002c5ca -0, 885000, 276480, 0xb243dda5 -0, 892500, 276480, 0x1700efbb -0, 900000, 276480, 0x8f316c66 +0, 3754, 276480, 0x5f7a0d4f +0, 7507, 276480, 0x5f7a0d4f +0, 11261, 276480, 0x5f7a0d4f +0, 15015, 276480, 0x5f7a0d4f +0, 18769, 276480, 0x5f7a0d4f +0, 22522, 276480, 0x5f7a0d4f +0, 26276, 276480, 0x5f7a0d4f +0, 30030, 276480, 0x5f7a0d4f +0, 33784, 276480, 0x5f7a0d4f +0, 37537, 276480, 0x5f7a0d4f +0, 41291, 276480, 0x5f7a0d4f +0, 45045, 276480, 0x5f7a0d4f +0, 48799, 276480, 0x5f7a0d4f +0, 52552, 276480, 0x5f7a0d4f +0, 56306, 276480, 0x5f7a0d4f +0, 60060, 276480, 0x5f7a0d4f +0, 63814, 276480, 0x5f7a0d4f +0, 67567, 276480, 0x5f7a0d4f +0, 71321, 276480, 0x5f7a0d4f +0, 75075, 276480, 0x5f7a0d4f +0, 78829, 276480, 0x5f7a0d4f +0, 82582, 276480, 0x5f7a0d4f +0, 86336, 276480, 0x5f7a0d4f +0, 90090, 276480, 0x5f7a0d4f +0, 93844, 276480, 0x5f7a0d4f +0, 97597, 276480, 0x5f7a0d4f +0, 101351, 276480, 0x5f7a0d4f +0, 105105, 276480, 0x5f7a0d4f +0, 108859, 276480, 0x5f7a0d4f +0, 112612, 276480, 0x5f7a0d4f +0, 116366, 276480, 0x5f7a0d4f +0, 120120, 276480, 0x5f7a0d4f +0, 123874, 276480, 0x75641594 +0, 127627, 276480, 0x32ee3526 +0, 131381, 276480, 0xcb53479a +0, 135135, 276480, 0x7ca9658e +0, 138889, 276480, 0x5ce39368 +0, 142642, 276480, 0x4ec1e418 +0, 146396, 276480, 0xb3790499 +0, 150150, 276480, 0xa9f1506f +0, 153904, 276480, 0x85cbc3b5 +0, 157657, 276480, 0x377c7b46 +0, 161411, 276480, 0x1a61d8db +0, 165165, 276480, 0xe1de7f0a +0, 168919, 276480, 0x756a4a2e +0, 172672, 276480, 0xcb379547 +0, 176426, 276480, 0xbae14484 +0, 180180, 276480, 0x8e12331c +0, 183934, 276480, 0x99c085be +0, 187687, 276480, 0xe479ffed +0, 191441, 276480, 0x99c82949 +0, 195195, 276480, 0xac7672dd +0, 198949, 276480, 0x1e4fae19 +0, 202702, 276480, 0x776412ef +0, 206456, 276480, 0x7d9b579f +0, 210210, 276480, 0x1cd1ab29 +0, 213964, 276480, 0x58ce0f38 +0, 217717, 276480, 0x5ab69b27 +0, 221471, 276480, 0x0afad610 +0, 225225, 276480, 0x9eca3f11 +0, 228979, 276480, 0xc3db9706 +0, 232732, 276480, 0xc9c57884 +0, 236486, 276480, 0xd9fbb2cf +0, 240240, 276480, 0xdc07f3c9 +0, 243994, 276480, 0x000b5269 +0, 247747, 276480, 0x27ff7a5d +0, 251501, 276480, 0xd92e2017 +0, 255255, 276480, 0x18d4b27d +0, 259009, 276480, 0x70647530 +0, 262762, 276480, 0x97612c4b +0, 266516, 276480, 0xc9d4ac78 +0, 270270, 276480, 0x4ec4d57f +0, 274024, 276480, 0xdf4e04d7 +0, 277777, 276480, 0xbd98f57c +0, 281531, 276480, 0x7247ea3e +0, 285285, 276480, 0xa5d670ec +0, 289039, 276480, 0x5163b29b +0, 292792, 276480, 0x99170e64 +0, 296546, 276480, 0x37f4c0b0 +0, 300300, 276480, 0x7a4f2561 +0, 304053, 276480, 0x8a4e991f +0, 307807, 276480, 0x6a45425f +0, 311561, 276480, 0x1f0e2bb6 +0, 315315, 276480, 0xd75482c6 +0, 319068, 276480, 0x7bf6b1ef +0, 322822, 276480, 0x6de1e34b +0, 326576, 276480, 0x4526c89b +0, 330330, 276480, 0xf964e18e +0, 334083, 276480, 0xdcaaa99a +0, 337837, 276480, 0xd1e98808 +0, 341591, 276480, 0x556b2365 +0, 345345, 276480, 0x0cf65540 +0, 349098, 276480, 0x6e2d524e +0, 352852, 276480, 0x22c50a3d +0, 356606, 276480, 0x293f19af +0, 360360, 276480, 0xf4b1c461 +0, 364113, 276480, 0x62b76407 +0, 367867, 276480, 0x51e9b3eb +0, 371621, 276480, 0x7b910bc7 +0, 375375, 276480, 0x6dd14ca6 +0, 379128, 276480, 0x441f7afd +0, 382882, 276480, 0xfb01efc6 +0, 386636, 276480, 0x4f73ccea +0, 390390, 276480, 0x5ac8e06f +0, 394143, 276480, 0x294bb441 +0, 397897, 276480, 0xe04ac45e +0, 401651, 276480, 0xa7a38d41 +0, 405405, 276480, 0xf688a3ed +0, 409158, 276480, 0x58f275ea +0, 412912, 276480, 0xf0b3b71b +0, 416666, 276480, 0x3ce773bf +0, 420420, 276480, 0x01840548 +0, 424173, 276480, 0x674e34e4 +0, 427927, 276480, 0x41dda2d9 +0, 431681, 276480, 0xc5b60838 +0, 435435, 276480, 0x9b209f41 +0, 439188, 276480, 0xf46ba7fb +0, 442942, 276480, 0x28b54815 +0, 446696, 276480, 0xb605a933 +0, 450450, 276480, 0x34484aff +0, 454203, 276480, 0xaf2b5d89 +0, 457957, 276480, 0x8facba58 +0, 461711, 276480, 0xbbe3e99f +0, 465465, 276480, 0x02162c7c +0, 469218, 276480, 0x28a63236 +0, 472972, 276480, 0x1ad43fd7 +0, 476726, 276480, 0xe37883e5 +0, 480480, 276480, 0x2b8a89c5 +0, 484233, 276480, 0x71507bd2 +0, 487987, 276480, 0x35626022 +0, 491741, 276480, 0x461fc3e7 +0, 495495, 276480, 0xce5af1ec +0, 499248, 276480, 0x7c1139b3 +0, 503002, 276480, 0x7fd73a99 +0, 506756, 276480, 0x4ae4c3a6 +0, 510510, 276480, 0xcb60725a +0, 514263, 276480, 0xb52e1aa2 +0, 518017, 276480, 0xd6f82cae +0, 521771, 276480, 0x6310e665 +0, 525525, 276480, 0xfa88a483 +0, 529278, 276480, 0xf88f75d4 +0, 533032, 276480, 0x04a8e3ee +0, 536786, 276480, 0x54766a12 +0, 540540, 276480, 0x0b41f0d7 +0, 544293, 276480, 0xa29f5b01 +0, 548047, 276480, 0x754ceaf5 +0, 551801, 276480, 0x150c0423 +0, 555555, 276480, 0xde084059 +0, 559308, 276480, 0x5a38b4af +0, 563062, 276480, 0xfcebc261 +0, 566816, 276480, 0x0eb9770d +0, 570570, 276480, 0x046394ae +0, 574323, 276480, 0x3d3ca985 +0, 578077, 276480, 0x94a03c75 +0, 581831, 276480, 0x800eea2d +0, 585585, 276480, 0x6a841f41 +0, 589338, 276480, 0x2f98911c +0, 593092, 276480, 0x923b9937 +0, 596846, 276480, 0xe82f8e0f +0, 600600, 276480, 0xee82d657 +0, 604353, 276480, 0xefab7ffd +0, 608107, 276480, 0x6b9fbc80 +0, 611861, 276480, 0x4a1ada47 +0, 615614, 276480, 0x6d4b49d7 +0, 619368, 276480, 0xe4bdbd1e +0, 623122, 276480, 0x225a56c0 +0, 626876, 276480, 0xd4adadad +0, 630629, 276480, 0xff4e1a8c +0, 634383, 276480, 0xf58b1b7c +0, 638137, 276480, 0xbaffcdcc +0, 641891, 276480, 0x374f88f0 +0, 645644, 276480, 0x3d861ae6 +0, 649398, 276480, 0xeb6eb88f +0, 653152, 276480, 0xdb753d35 +0, 656906, 276480, 0x9aa543af +0, 660659, 276480, 0xb24c8016 +0, 664413, 276480, 0xea80a82e +0, 668167, 276480, 0x2aae902a +0, 671921, 276480, 0x5bba3cfb +0, 675674, 276480, 0x5c6e97a9 +0, 679428, 276480, 0x9b9ee961 +0, 683182, 276480, 0xaa12b6fd +0, 686936, 276480, 0xe9d2439f +0, 690689, 276480, 0xbf09053c +0, 694443, 276480, 0x50c31e73 +0, 698197, 276480, 0xdd9fb89f +0, 701951, 276480, 0x3e4e5aec +0, 705704, 276480, 0x0b752d28 +0, 709458, 276480, 0xaf82399a +0, 713212, 276480, 0x7ce5f23c +0, 716966, 276480, 0xad135d0f +0, 720719, 276480, 0x55dadd30 +0, 724473, 276480, 0x5aaa7519 +0, 728227, 276480, 0xe45a5599 +0, 731981, 276480, 0xc8e89913 +0, 735734, 276480, 0x2f447fd3 +0, 739488, 276480, 0x704411fb +0, 743242, 276480, 0x9d7430a1 +0, 746996, 276480, 0x24dd5fd3 +0, 750749, 276480, 0x51cb657c +0, 754503, 276480, 0x2c230702 +0, 758257, 276480, 0x4a4f76cd +0, 762011, 276480, 0xdcd71e88 +0, 765764, 276480, 0x87160f99 +0, 769518, 276480, 0x27f54854 +0, 773272, 276480, 0x694d76e3 +0, 777026, 276480, 0xcbe93c19 +0, 780779, 276480, 0x50742e1b +0, 784533, 276480, 0x525463e2 +0, 788287, 276480, 0x819898f9 +0, 792041, 276480, 0x08fac755 +0, 795794, 276480, 0x35c46927 +0, 799548, 276480, 0xeeed00fc +0, 803302, 276480, 0xb6f99ee3 +0, 807056, 276480, 0xd87f4c73 +0, 810809, 276480, 0xde97d9fd +0, 814563, 276480, 0xefc83107 +0, 818317, 276480, 0xbb22e024 +0, 822071, 276480, 0x53a7cfcb +0, 825824, 276480, 0xbe1fbb19 +0, 829578, 276480, 0x300f922a +0, 833332, 276480, 0x826fc3bd +0, 837086, 276480, 0x679aa57a +0, 840839, 276480, 0x5497097b +0, 844593, 276480, 0x679a53f8 +0, 848347, 276480, 0x976c9e93 +0, 852101, 276480, 0xe80f87f2 +0, 855854, 276480, 0xdc2d7c6c +0, 859608, 276480, 0xb194656e +0, 863362, 276480, 0xf002c5ca +0, 867116, 276480, 0x43fc1c64 +0, 870869, 276480, 0xf62d8581 +0, 874623, 276480, 0xb243dda5 +0, 878377, 276480, 0x1700efbb +0, 882131, 276480, 0x9ebe6ba2 +0, 885884, 276480, 0x8f316c66 +0, 889638, 276480, 0x6348ecf5 +0, 893392, 276480, 0x34b5b78a +0, 897146, 276480, 0xcbf66922 diff --git a/tests/ref/fate/rv30 b/tests/ref/fate/rv30 index 6c99871eb6..a3c5dcfbbf 100644 --- a/tests/ref/fate/rv30 +++ b/tests/ref/fate/rv30 @@ -1,46 +1,109 @@ 0, 0, 126720, 0xcefaec47 -0, 7500, 126720, 0xa416ece5 -0, 15000, 126720, 0xa416ece5 -0, 22500, 126720, 0xa416ece5 -0, 30000, 126720, 0xcc10f4b7 -0, 37500, 126720, 0xeb6fb8d7 -0, 45000, 126720, 0xda71b917 -0, 52500, 126720, 0xbb1abbb7 -0, 60000, 126720, 0x273fbc37 -0, 67500, 126720, 0x16eebbd7 -0, 75000, 126720, 0x105eb927 -0, 82500, 126720, 0x7fa3ae27 -0, 90000, 126720, 0xd115a757 -0, 97500, 126720, 0x04e7897c -0, 105000, 126720, 0x68cfda2b -0, 112500, 126720, 0xe572dfc9 -0, 120000, 126720, 0xbc3cc34f -0, 127500, 126720, 0xcf8cb0e2 -0, 135000, 126720, 0x75ae61b6 -0, 142500, 126720, 0x554fe3e4 -0, 150000, 126720, 0x72ecea95 -0, 157500, 126720, 0x5d00b5fe -0, 165000, 126720, 0xe39bba0d -0, 172500, 126720, 0x9c21bad8 -0, 180000, 126720, 0x72f2a47d -0, 187500, 126720, 0x4f639ebe -0, 195000, 126720, 0x534a10cc -0, 202500, 126720, 0xfdca11d3 -0, 210000, 126720, 0x0c735615 -0, 217500, 126720, 0x0eaf0c1b -0, 225000, 126720, 0xce5e6794 -0, 232500, 126720, 0x14cf7974 -0, 240000, 126720, 0xbc513f2a -0, 247500, 126720, 0xbc303fae -0, 255000, 126720, 0xd9f67585 -0, 262500, 126720, 0x3378251f -0, 270000, 126720, 0xb3ed5911 -0, 277500, 126720, 0xc15a3577 -0, 285000, 126720, 0x0a24f256 -0, 292500, 126720, 0xfab9c45d -0, 300000, 126720, 0x45464610 -0, 307500, 126720, 0xfe2e057d -0, 315000, 126720, 0x23efdc35 -0, 322500, 126720, 0x4d888b2e -0, 330000, 126720, 0xdd0d74df -0, 337500, 126720, 0x08382b8e +0, 3003, 126720, 0xa416ece5 +0, 6006, 126720, 0xa416ece5 +0, 9009, 126720, 0xa416ece5 +0, 12012, 126720, 0x60d6ed27 +0, 15015, 126720, 0x259af497 +0, 18018, 126720, 0x5e6ff4d7 +0, 21021, 126720, 0xcc10f4b7 +0, 24024, 126720, 0x763ab817 +0, 27027, 126720, 0xeb6fb8d7 +0, 30030, 126720, 0xda71b917 +0, 33033, 126720, 0x0967b8f7 +0, 36036, 126720, 0x4b62b947 +0, 39039, 126720, 0xbb1abbb7 +0, 42042, 126720, 0x273fbc37 +0, 45045, 126720, 0x16eebbd7 +0, 48048, 126720, 0x105eb927 +0, 51051, 126720, 0x7fa3ae27 +0, 54054, 126720, 0x722e99f7 +0, 57057, 126720, 0x5ac9a827 +0, 60060, 126720, 0x07beba77 +0, 63063, 126720, 0x29d6a887 +0, 66066, 126720, 0xa5caab87 +0, 69069, 126720, 0x9ca7aac7 +0, 72072, 126720, 0xb7debcd7 +0, 75075, 126720, 0xd115a757 +0, 78078, 126720, 0x6ddaef32 +0, 81081, 126720, 0xde1bb900 +0, 84084, 126720, 0xac6c071b +0, 87087, 126720, 0x04e7897c +0, 90090, 126720, 0x5eee050f +0, 93093, 126720, 0xe675be59 +0, 96096, 126720, 0xdc3e0837 +0, 99099, 126720, 0x68cfda2b +0, 102102, 126720, 0xe572dfc9 +0, 105105, 126720, 0x582fb176 +0, 108108, 126720, 0xa9477df0 +0, 111111, 126720, 0xbc3cc34f +0, 114114, 126720, 0xcf8cb0e2 +0, 117117, 126720, 0xcff1db35 +0, 120120, 126720, 0xc6e10f9f +0, 123123, 126720, 0x75ae61b6 +0, 126126, 126720, 0x12af3119 +0, 129129, 126720, 0x85597543 +0, 132132, 126720, 0x68c27aca +0, 135135, 126720, 0x554fe3e4 +0, 138138, 126720, 0x72ecea95 +0, 141141, 126720, 0xf4d003d1 +0, 144144, 126720, 0x9bf6a605 +0, 147147, 126720, 0x5d00b5fe +0, 150150, 126720, 0x93f7b040 +0, 153153, 126720, 0x0d6ad154 +0, 156156, 126720, 0x4be8b4ea +0, 159159, 126720, 0xe39bba0d +0, 162162, 126720, 0x9c21bad8 +0, 165165, 126720, 0xa567f25b +0, 168168, 126720, 0x7a82663a +0, 171171, 126720, 0x72f2a47d +0, 174174, 126720, 0x4f639ebe +0, 177177, 126720, 0xab0fce83 +0, 180180, 126720, 0x6cf87d39 +0, 183183, 126720, 0x534a10cc +0, 186186, 126720, 0x6bbcf44c +0, 189189, 126720, 0xfdca11d3 +0, 192192, 126720, 0x7e58f5a6 +0, 195195, 126720, 0x5fd753d8 +0, 198198, 126720, 0x0c735615 +0, 201201, 126720, 0x2a034ebf +0, 204204, 126720, 0xeaf3dd0b +0, 207207, 126720, 0x0eaf0c1b +0, 210210, 126720, 0xce5e6794 +0, 213213, 126720, 0xf27c31c3 +0, 216216, 126720, 0xb64af168 +0, 219219, 126720, 0x14cf7974 +0, 222222, 126720, 0x1c2a513d +0, 225225, 126720, 0xa3f515ab +0, 228228, 126720, 0xcfd62765 +0, 231231, 126720, 0xbc513f2a +0, 234234, 126720, 0xbc303fae +0, 237237, 126720, 0x2f8f69b9 +0, 240240, 126720, 0x0a22cc69 +0, 243243, 126720, 0xd9f67585 +0, 246246, 126720, 0x20403001 +0, 249249, 126720, 0xf92b2a25 +0, 252252, 126720, 0x3c170aad +0, 255255, 126720, 0x3378251f +0, 258258, 126720, 0xb3ed5911 +0, 261261, 126720, 0x35d24ef8 +0, 264264, 126720, 0x8da30275 +0, 267267, 126720, 0xc15a3577 +0, 270270, 126720, 0xf2942f53 +0, 273273, 126720, 0x44d8304a +0, 276276, 126720, 0xd688a932 +0, 279279, 126720, 0x0a24f256 +0, 282282, 126720, 0xfab9c45d +0, 285285, 126720, 0x10e939ce +0, 288288, 126720, 0x97fcaa3a +0, 291291, 126720, 0x45464610 +0, 294294, 126720, 0xfe2e057d +0, 297297, 126720, 0x0b6718ae +0, 300300, 126720, 0x5284da7b +0, 303303, 126720, 0x23efdc35 +0, 306306, 126720, 0xc387b2b3 +0, 309309, 126720, 0xc9e92bf1 +0, 312312, 126720, 0xfbf20a01 +0, 315315, 126720, 0x4d888b2e +0, 318318, 126720, 0xdd0d74df +0, 321321, 126720, 0x49d07aa4 +0, 324324, 126720, 0x08382b8e