static int matroska_parse_tracks(AVFormatContext *s)

{

    MatroskaDemuxContext *matroska = s->priv_data;

    MatroskaTrack *tracks = matroska->tracks.elem;

    AVStream *st;

    int i, j, ret;

    int k;

    for (i = 0; i < matroska->tracks.nb_elem; i++) {

        MatroskaTrack *track = &tracks[i];

        enum AVCodecID codec_id = AV_CODEC_ID_NONE;

        EbmlList *encodings_list = &track->encodings;

        MatroskaTrackEncoding *encodings = encodings_list->elem;

        uint8_t *extradata = NULL;

        int extradata_size = 0;

        int extradata_offset = 0;

        uint32_t fourcc = 0;

        AVIOContext b;

        char* key_id_base64 = NULL;

        int bit_depth = -1;

        /* Apply some sanity checks. */

        if (track->type != MATROSKA_TRACK_TYPE_VIDEO &&

            track->type != MATROSKA_TRACK_TYPE_AUDIO &&

            track->type != MATROSKA_TRACK_TYPE_SUBTITLE &&

            track->type != MATROSKA_TRACK_TYPE_METADATA) {

            av_log(matroska->ctx, AV_LOG_INFO,

                   "Unknown or unsupported track type %"PRIu64"\n",

                   track->type);

            continue;

        }

        if (!track->codec_id)

            continue;

        if (track->audio.samplerate < 0 || track->audio.samplerate > INT_MAX ||

            isnan(track->audio.samplerate)) {

            av_log(matroska->ctx, AV_LOG_WARNING,

                   "Invalid sample rate %f, defaulting to 8000 instead.\n",

                   track->audio.samplerate);

            track->audio.samplerate = 8000;

        }

        if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {

            if (!track->default_duration && track->video.frame_rate > 0)

                track->default_duration = 1000000000 / track->video.frame_rate;

            if (track->video.display_width == -1)

                track->video.display_width = track->video.pixel_width;

            if (track->video.display_height == -1)

                track->video.display_height = track->video.pixel_height;

            if (track->video.color_space.size == 4)

                fourcc = AV_RL32(track->video.color_space.data);

        } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {

            if (!track->audio.out_samplerate)

                track->audio.out_samplerate = track->audio.samplerate;

        }

        if (encodings_list->nb_elem > 1) {

            av_log(matroska->ctx, AV_LOG_ERROR,

                   "Multiple combined encodings not supported");

        } else if (encodings_list->nb_elem == 1) {

            if (encodings[0].type) {

                if (encodings[0].encryption.key_id.size > 0) {

                    /* Save the encryption key id to be stored later as a

                       metadata tag. */

                    const int b64_size = AV_BASE64_SIZE(encodings[0].encryption.key_id.size);

                    key_id_base64 = av_malloc(b64_size);

                    if (key_id_base64 == NULL)

                        return AVERROR(ENOMEM);

                    av_base64_encode(key_id_base64, b64_size,

                                     encodings[0].encryption.key_id.data,

                                     encodings[0].encryption.key_id.size);

                } else {

                    encodings[0].scope = 0;

                    av_log(matroska->ctx, AV_LOG_ERROR,

                           "Unsupported encoding type");

                }

            } else if (

#if CONFIG_ZLIB

                 encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB  &&

#endif

#if CONFIG_BZLIB

                 encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB &&

#endif

#if CONFIG_LZO

                 encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO   &&

#endif

                 encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) {

                encodings[0].scope = 0;

                av_log(matroska->ctx, AV_LOG_ERROR,

                       "Unsupported encoding type");

            } else if (track->codec_priv.size && encodings[0].scope & 2) {

                uint8_t *codec_priv = track->codec_priv.data;

                int ret = matroska_decode_buffer(&track->codec_priv.data,

                                                 &track->codec_priv.size,

                                                 track);

                if (ret < 0) {

                    track->codec_priv.data = NULL;

                    track->codec_priv.size = 0;

                    av_log(matroska->ctx, AV_LOG_ERROR,

                           "Failed to decode codec private data\n");

                }

                if (codec_priv != track->codec_priv.data)

                    av_free(codec_priv);

            }

        }

        for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) {

            if (!strncmp(ff_mkv_codec_tags[j].str, track->codec_id,

                         strlen(ff_mkv_codec_tags[j].str))) {

                codec_id = ff_mkv_codec_tags[j].id;

                break;

            }

        }

        st = track->stream = avformat_new_stream(s, NULL);

        if (!st) {

            av_free(key_id_base64);

            return AVERROR(ENOMEM);

        }

        if (key_id_base64) {

            /* export encryption key id as base64 metadata tag */

            av_dict_set(&st->metadata, "enc_key_id", key_id_base64, 0);

            av_freep(&key_id_base64);

        }

        if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") &&

             track->codec_priv.size >= 40               &&

            track->codec_priv.data) {

            track->ms_compat    = 1;

            bit_depth           = AV_RL16(track->codec_priv.data + 14);

            fourcc              = AV_RL32(track->codec_priv.data + 16);

            codec_id            = ff_codec_get_id(ff_codec_bmp_tags,

                                                  fourcc);

            if (!codec_id)

                codec_id        = ff_codec_get_id(ff_codec_movvideo_tags,

                                                  fourcc);

            extradata_offset    = 40;

        } else if (!strcmp(track->codec_id, "A_MS/ACM") &&

                   track->codec_priv.size >= 14         &&

                   track->codec_priv.data) {

            int ret;

            ffio_init_context(&b, track->codec_priv.data,

                              track->codec_priv.size,

                              0, NULL, NULL, NULL, NULL);

            ret = ff_get_wav_header(s, &b, st->codecpar, track->codec_priv.size, 0);

            if (ret < 0)

                return ret;

            codec_id         = st->codecpar->codec_id;

            fourcc           = st->codecpar->codec_tag;

            extradata_offset = FFMIN(track->codec_priv.size, 18);

        } else if (!strcmp(track->codec_id, "A_QUICKTIME")

                   /* Normally 36, but allow noncompliant private data */

                   && (track->codec_priv.size >= 32)

                   && (track->codec_priv.data)) {

            uint16_t sample_size;

            int ret = get_qt_codec(track, &fourcc, &codec_id);

            if (ret < 0)

                return ret;

            sample_size = AV_RB16(track->codec_priv.data + 26);

            if (fourcc == 0) {

                if (sample_size == 8) {

                    fourcc = MKTAG('r','a','w',' ');

                    codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);

                } else if (sample_size == 16) {

                    fourcc = MKTAG('t','w','o','s');

                    codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);

                }

            }

            if ((fourcc == MKTAG('t','w','o','s') ||

                    fourcc == MKTAG('s','o','w','t')) &&

                    sample_size == 8)

                codec_id = AV_CODEC_ID_PCM_S8;

        } else if (!strcmp(track->codec_id, "V_QUICKTIME") &&

                   (track->codec_priv.size >= 21)          &&

                   (track->codec_priv.data)) {

            int ret = get_qt_codec(track, &fourcc, &codec_id);

            if (ret < 0)

                return ret;

            if (codec_id == AV_CODEC_ID_NONE && AV_RL32(track->codec_priv.data+4) == AV_RL32("SMI ")) {

                fourcc = MKTAG('S','V','Q','3');

                codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc);

            }

            if (codec_id == AV_CODEC_ID_NONE)

                av_log(matroska->ctx, AV_LOG_ERROR,

                       "mov FourCC not found %s.\n", av_fourcc2str(fourcc));

            if (track->codec_priv.size >= 86) {

                bit_depth = AV_RB16(track->codec_priv.data + 82);

                ffio_init_context(&b, track->codec_priv.data,

                                  track->codec_priv.size,

                                  0, NULL, NULL, NULL, NULL);

                if (ff_get_qtpalette(codec_id, &b, track->palette)) {

                    bit_depth &= 0x1F;

                    track->has_palette = 1;

                }

            }

        } else if (codec_id == AV_CODEC_ID_PCM_S16BE) {

            switch (track->audio.bitdepth) {

            case  8:

                codec_id = AV_CODEC_ID_PCM_U8;

                break;

            case 24:

                codec_id = AV_CODEC_ID_PCM_S24BE;

                break;

            case 32:

                codec_id = AV_CODEC_ID_PCM_S32BE;

                break;

            }

        } else if (codec_id == AV_CODEC_ID_PCM_S16LE) {

            switch (track->audio.bitdepth) {

            case  8:

                codec_id = AV_CODEC_ID_PCM_U8;

                break;

            case 24:

                codec_id = AV_CODEC_ID_PCM_S24LE;

                break;

            case 32:

                codec_id = AV_CODEC_ID_PCM_S32LE;

                break;

            }

        } else if (codec_id == AV_CODEC_ID_PCM_F32LE &&

                   track->audio.bitdepth == 64) {

            codec_id = AV_CODEC_ID_PCM_F64LE;

        } else if (codec_id == AV_CODEC_ID_AAC && !track->codec_priv.size) {

            int profile = matroska_aac_profile(track->codec_id);

            int sri     = matroska_aac_sri(track->audio.samplerate);

            extradata   = av_mallocz(5 + AV_INPUT_BUFFER_PADDING_SIZE);

            if (!extradata)

                return AVERROR(ENOMEM);

            extradata[0] = (profile << 3) | ((sri & 0x0E) >> 1);

            extradata[1] = ((sri & 0x01) << 7) | (track->audio.channels << 3);

            if (strstr(track->codec_id, "SBR")) {

                sri            = matroska_aac_sri(track->audio.out_samplerate);

                extradata[2]   = 0x56;

                extradata[3]   = 0xE5;

                extradata[4]   = 0x80 | (sri << 3);

                extradata_size = 5;

            } else

                extradata_size = 2;

        } else if (codec_id == AV_CODEC_ID_ALAC && track->codec_priv.size && track->codec_priv.size < INT_MAX - 12 - AV_INPUT_BUFFER_PADDING_SIZE) {

            /* Only ALAC's magic cookie is stored in Matroska's track headers.

             * Create the "atom size", "tag", and "tag version" fields the

             * decoder expects manually. */

            extradata_size = 12 + track->codec_priv.size;

            extradata      = av_mallocz(extradata_size +

                                        AV_INPUT_BUFFER_PADDING_SIZE);

            if (!extradata)

                return AVERROR(ENOMEM);

            AV_WB32(extradata, extradata_size);

            memcpy(&extradata[4], "alac", 4);

            AV_WB32(&extradata[8], 0);

            memcpy(&extradata[12], track->codec_priv.data,

                   track->codec_priv.size);

        } else if (codec_id == AV_CODEC_ID_TTA) {

            extradata_size = 30;

            extradata      = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);

            if (!extradata)

                return AVERROR(ENOMEM);

            ffio_init_context(&b, extradata, extradata_size, 1,

                              NULL, NULL, NULL, NULL);

            avio_write(&b, "TTA1", 4);

            avio_wl16(&b, 1);

            if (track->audio.channels > UINT16_MAX ||

                track->audio.bitdepth > UINT16_MAX) {

                av_log(matroska->ctx, AV_LOG_WARNING,

                       "Too large audio channel number %"PRIu64

                       " or bitdepth %"PRIu64". Skipping track.\n",

                       track->audio.channels, track->audio.bitdepth);

                av_freep(&extradata);

                if (matroska->ctx->error_recognition & AV_EF_EXPLODE)

                    return AVERROR_INVALIDDATA;

                else

                    continue;

            }

            avio_wl16(&b, track->audio.channels);

            avio_wl16(&b, track->audio.bitdepth);

            if (track->audio.out_samplerate < 0 || track->audio.out_samplerate > INT_MAX)

                return AVERROR_INVALIDDATA;

            avio_wl32(&b, track->audio.out_samplerate);

            avio_wl32(&b, av_rescale((matroska->duration * matroska->time_scale),

                                     track->audio.out_samplerate,

                                     AV_TIME_BASE * 1000));

        } else if (codec_id == AV_CODEC_ID_RV10 ||

                   codec_id == AV_CODEC_ID_RV20 ||

                   codec_id == AV_CODEC_ID_RV30 ||

                   codec_id == AV_CODEC_ID_RV40) {

            extradata_offset = 26;

        } else if (codec_id == AV_CODEC_ID_RA_144) {

            track->audio.out_samplerate = 8000;

            track->audio.channels       = 1;

        } else if ((codec_id == AV_CODEC_ID_RA_288 ||

                    codec_id == AV_CODEC_ID_COOK   ||

                    codec_id == AV_CODEC_ID_ATRAC3 ||

                    codec_id == AV_CODEC_ID_SIPR)

                      && track->codec_priv.data) {

            int flavor;

            ffio_init_context(&b, track->codec_priv.data,

                              track->codec_priv.size,

                              0, NULL, NULL, NULL, NULL);

            avio_skip(&b, 22);

            flavor                       = avio_rb16(&b);

            track->audio.coded_framesize = avio_rb32(&b);

            avio_skip(&b, 12);

            track->audio.sub_packet_h    = avio_rb16(&b);

            track->audio.frame_size      = avio_rb16(&b);

            track->audio.sub_packet_size = avio_rb16(&b);

            if (flavor                        < 0 ||

                track->audio.coded_framesize <= 0 ||

                track->audio.sub_packet_h    <= 0 ||

                track->audio.frame_size      <= 0 ||

                track->audio.sub_packet_size <= 0 && codec_id != AV_CODEC_ID_SIPR)

                return AVERROR_INVALIDDATA;

            track->audio.buf = av_malloc_array(track->audio.sub_packet_h,

                                               track->audio.frame_size);

            if (!track->audio.buf)

                return AVERROR(ENOMEM);

            if (codec_id == AV_CODEC_ID_RA_288) {

                st->codecpar->block_align = track->audio.coded_framesize;

                track->codec_priv.size = 0;

            } else {

                if (codec_id == AV_CODEC_ID_SIPR && flavor < 4) {

                    static const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 };

                    track->audio.sub_packet_size = ff_sipr_subpk_size[flavor];

                    st->codecpar->bit_rate          = sipr_bit_rate[flavor];

                }

                st->codecpar->block_align = track->audio.sub_packet_size;

                extradata_offset       = 78;

            }

        } else if (codec_id == AV_CODEC_ID_FLAC && track->codec_priv.size) {

            ret = matroska_parse_flac(s, track, &extradata_offset);

            if (ret < 0)

                return ret;

        } else if (codec_id == AV_CODEC_ID_PRORES && track->codec_priv.size == 4) {

            fourcc = AV_RL32(track->codec_priv.data);

        }

        track->codec_priv.size -= extradata_offset;

        if (codec_id == AV_CODEC_ID_NONE)

            av_log(matroska->ctx, AV_LOG_INFO,

                   "Unknown/unsupported AVCodecID %s.\n", track->codec_id);

        if (track->time_scale < 0.01)

            track->time_scale = 1.0;

        avpriv_set_pts_info(st, 64, matroska->time_scale * track->time_scale,

                            1000 * 1000 * 1000);    /* 64 bit pts in ns */

        /* convert the delay from ns to the track timebase */

        track->codec_delay_in_track_tb = av_rescale_q(track->codec_delay,

                                          (AVRational){ 1, 1000000000 },

                                          st->time_base);

        st->codecpar->codec_id = codec_id;

        if (strcmp(track->language, "und"))

            av_dict_set(&st->metadata, "language", track->language, 0);

        av_dict_set(&st->metadata, "title", track->name, 0);

        if (track->flag_default)

            st->disposition |= AV_DISPOSITION_DEFAULT;

        if (track->flag_forced)

            st->disposition |= AV_DISPOSITION_FORCED;

        if (!st->codecpar->extradata) {

            if (extradata) {

                st->codecpar->extradata      = extradata;

                st->codecpar->extradata_size = extradata_size;

            } else if (track->codec_priv.data && track->codec_priv.size > 0) {

                if (ff_alloc_extradata(st->codecpar, track->codec_priv.size))

                    return AVERROR(ENOMEM);

                memcpy(st->codecpar->extradata,

                       track->codec_priv.data + extradata_offset,

                       track->codec_priv.size);

            }

        }

        if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {

            MatroskaTrackPlane *planes = track->operation.combine_planes.elem;

            int display_width_mul  = 1;

            int display_height_mul = 1;

            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;

            st->codecpar->codec_tag  = fourcc;

            if (bit_depth >= 0)

                st->codecpar->bits_per_coded_sample = bit_depth;

            st->codecpar->width      = track->video.pixel_width;

            st->codecpar->height     = track->video.pixel_height;

            if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED)

                st->codecpar->field_order = mkv_field_order(matroska, track->video.field_order);

            else if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE)

                st->codecpar->field_order = AV_FIELD_PROGRESSIVE;

            if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB)

                mkv_stereo_mode_display_mul(track->video.stereo_mode, &display_width_mul, &display_height_mul);

            if (track->video.display_unit < MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN) {

                av_reduce(&st->sample_aspect_ratio.num,

                          &st->sample_aspect_ratio.den,

                          st->codecpar->height * track->video.display_width  * display_width_mul,

                          st->codecpar->width  * track->video.display_height * display_height_mul,

                          255);

            }

            if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)

                st->need_parsing = AVSTREAM_PARSE_HEADERS;

            if (track->default_duration) {

                av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,

                          1000000000, track->default_duration, 30000);

#if FF_API_R_FRAME_RATE

                if (   st->avg_frame_rate.num < st->avg_frame_rate.den * 1000LL

                    && st->avg_frame_rate.num > st->avg_frame_rate.den * 5LL)

                    st->r_frame_rate = st->avg_frame_rate;

#endif

            }

            /* export stereo mode flag as metadata tag */

            if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB)

                av_dict_set(&st->metadata, "stereo_mode", ff_matroska_video_stereo_mode[track->video.stereo_mode], 0);

            /* export alpha mode flag as metadata tag  */

            if (track->video.alpha_mode)

                av_dict_set(&st->metadata, "alpha_mode", "1", 0);

            /* if we have virtual track, mark the real tracks */

            for (j=0; j < track->operation.combine_planes.nb_elem; j++) {

                char buf[32];

                if (planes[j].type >= MATROSKA_VIDEO_STEREO_PLANE_COUNT)

                    continue;

                snprintf(buf, sizeof(buf), "%s_%d",

                         ff_matroska_video_stereo_plane[planes[j].type], i);

                for (k=0; k < matroska->tracks.nb_elem; k++)

                    if (planes[j].uid == tracks[k].uid && tracks[k].stream) {

                        av_dict_set(&tracks[k].stream->metadata,

                                    "stereo_mode", buf, 0);

                        break;

                    }

            }

            // add stream level stereo3d side data if it is a supported format

            if (track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB &&

                track->video.stereo_mode != 10 && track->video.stereo_mode != 12) {

                int ret = ff_mkv_stereo3d_conv(st, track->video.stereo_mode);

                if (ret < 0)

                    return ret;

            }

            ret = mkv_parse_video_color(st, track);

            if (ret < 0)

                return ret;

            ret = mkv_parse_video_projection(st, track);

            if (ret < 0)

                return ret;

        } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {

            st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;

            st->codecpar->codec_tag   = fourcc;

            st->codecpar->sample_rate = track->audio.out_samplerate;

            st->codecpar->channels    = track->audio.channels;

            if (!st->codecpar->bits_per_coded_sample)

                st->codecpar->bits_per_coded_sample = track->audio.bitdepth;

            if (st->codecpar->codec_id == AV_CODEC_ID_MP3)

                st->need_parsing = AVSTREAM_PARSE_FULL;

            else if (st->codecpar->codec_id != AV_CODEC_ID_AAC)

                st->need_parsing = AVSTREAM_PARSE_HEADERS;

            if (track->codec_delay > 0) {

                st->codecpar->initial_padding = av_rescale_q(track->codec_delay,

                                                             (AVRational){1, 1000000000},

                                                             (AVRational){1, st->codecpar->codec_id == AV_CODEC_ID_OPUS ?

                                                                             48000 : st->codecpar->sample_rate});

            }

            if (track->seek_preroll > 0) {

                st->codecpar->seek_preroll = av_rescale_q(track->seek_preroll,

                                                          (AVRational){1, 1000000000},

                                                          (AVRational){1, st->codecpar->sample_rate});

            }

        } else if (codec_id == AV_CODEC_ID_WEBVTT) {

            st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;

            if (!strcmp(track->codec_id, "D_WEBVTT/CAPTIONS")) {

                st->disposition |= AV_DISPOSITION_CAPTIONS;

            } else if (!strcmp(track->codec_id, "D_WEBVTT/DESCRIPTIONS")) {

                st->disposition |= AV_DISPOSITION_DESCRIPTIONS;

            } else if (!strcmp(track->codec_id, "D_WEBVTT/METADATA")) {

                st->disposition |= AV_DISPOSITION_METADATA;

            }

        } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) {

            st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;

            if (st->codecpar->codec_id == AV_CODEC_ID_ASS)

                matroska->contains_ssa = 1;

        }

    }

    return 0;

}


static void vnc_display_close(VncDisplay *vd)

{

    size_t i;

    if (!vd) {

        return;

    }

    vd->is_unix = false;

    for (i = 0; i < vd->nlsock; i++) {

        if (vd->lsock_tag[i]) {

            g_source_remove(vd->lsock_tag[i]);

        }

        object_unref(OBJECT(vd->lsock[i]));

    }

    g_free(vd->lsock);

    g_free(vd->lsock_tag);

    vd->lsock = NULL;

    vd->lsock_tag = NULL;

    vd->nlsock = 0;

    for (i = 0; i < vd->nlwebsock; i++) {

        if (vd->lwebsock_tag[i]) {

            g_source_remove(vd->lwebsock_tag[i]);

        }

        object_unref(OBJECT(vd->lwebsock[i]));

    }

    g_free(vd->lwebsock);

    g_free(vd->lwebsock_tag);

    vd->lwebsock = NULL;

    vd->lwebsock_tag = NULL;

    vd->nlwebsock = 0;

    vd->auth = VNC_AUTH_INVALID;

    vd->subauth = VNC_AUTH_INVALID;

    if (vd->tlscreds) {

        object_unparent(OBJECT(vd->tlscreds));

        vd->tlscreds = NULL;

    }

    g_free(vd->tlsaclname);

    vd->tlsaclname = NULL;

    if (vd->lock_key_sync) {

        qemu_remove_led_event_handler(vd->led);

    }

}


static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)

{

    SCSIRequest *req = &r->req;

    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);

    uint64_t nb_sectors;

    int buflen = 0;

    int ret;

    switch (req->cmd.buf[0]) {

    case TEST_UNIT_READY:

        if (!bdrv_is_inserted(s->bs))

            goto not_ready;

	break;

    case REQUEST_SENSE:

        if (req->cmd.xfer < 4)

            goto illegal_request;

        memset(outbuf, 0, 4);

        buflen = 4;

        if (s->sense.key == NOT_READY && req->cmd.xfer >= 18) {

            memset(outbuf, 0, 18);

            buflen = 18;

            outbuf[7] = 10;

            /* asc 0x3a, ascq 0: Medium not present */

            outbuf[12] = 0x3a;

            outbuf[13] = 0;

        }

        outbuf[0] = 0xf0;

        outbuf[1] = 0;

        outbuf[2] = s->sense.key;

        scsi_disk_clear_sense(s);

        break;

    case INQUIRY:

        buflen = scsi_disk_emulate_inquiry(req, outbuf);

        if (buflen < 0)

            goto illegal_request;

	break;

    case MODE_SENSE:

    case MODE_SENSE_10:

        buflen = scsi_disk_emulate_mode_sense(req, outbuf);

        if (buflen < 0)

            goto illegal_request;

        break;

    case READ_TOC:

        buflen = scsi_disk_emulate_read_toc(req, outbuf);

        if (buflen < 0)

            goto illegal_request;

        break;

    case RESERVE:

        if (req->cmd.buf[1] & 1)

            goto illegal_request;

        break;

    case RESERVE_10:

        if (req->cmd.buf[1] & 3)

            goto illegal_request;

        break;

    case RELEASE:

        if (req->cmd.buf[1] & 1)

            goto illegal_request;

        break;

    case RELEASE_10:

        if (req->cmd.buf[1] & 3)

            goto illegal_request;

        break;

    case START_STOP:

        if (s->drive_kind == SCSI_CD && (req->cmd.buf[4] & 2)) {

            /* load/eject medium */

            bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));

        }

	break;

    case ALLOW_MEDIUM_REMOVAL:

        bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);

	break;

    case READ_CAPACITY:

        /* The normal LEN field for this command is zero.  */

	memset(outbuf, 0, 8);

	bdrv_get_geometry(s->bs, &nb_sectors);

        if (!nb_sectors)

            goto not_ready;

        nb_sectors /= s->cluster_size;

        /* Returned value is the address of the last sector.  */

        nb_sectors--;

        /* Remember the new size for read/write sanity checking. */

        s->max_lba = nb_sectors;

        /* Clip to 2TB, instead of returning capacity modulo 2TB. */

        if (nb_sectors > UINT32_MAX)

            nb_sectors = UINT32_MAX;

        outbuf[0] = (nb_sectors >> 24) & 0xff;

        outbuf[1] = (nb_sectors >> 16) & 0xff;

        outbuf[2] = (nb_sectors >> 8) & 0xff;

        outbuf[3] = nb_sectors & 0xff;

        outbuf[4] = 0;

        outbuf[5] = 0;

        outbuf[6] = s->cluster_size * 2;

        outbuf[7] = 0;

        buflen = 8;

	break;

    case SYNCHRONIZE_CACHE:

        ret = bdrv_flush(s->bs);

        if (ret < 0) {

            if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {

                return -1;

            }

        }

        break;

    case GET_CONFIGURATION:

        memset(outbuf, 0, 8);

        /* ??? This should probably return much more information.  For now

           just return the basic header indicating the CD-ROM profile.  */

        outbuf[7] = 8; // CD-ROM

        buflen = 8;

        break;

    case SERVICE_ACTION_IN:

        /* Service Action In subcommands. */

        if ((req->cmd.buf[1] & 31) == 0x10) {

            DPRINTF("SAI READ CAPACITY(16)\n");

            memset(outbuf, 0, req->cmd.xfer);

            bdrv_get_geometry(s->bs, &nb_sectors);

            if (!nb_sectors)

                goto not_ready;

            nb_sectors /= s->cluster_size;

            /* Returned value is the address of the last sector.  */

            nb_sectors--;

            /* Remember the new size for read/write sanity checking. */

            s->max_lba = nb_sectors;

            outbuf[0] = (nb_sectors >> 56) & 0xff;

            outbuf[1] = (nb_sectors >> 48) & 0xff;

            outbuf[2] = (nb_sectors >> 40) & 0xff;

            outbuf[3] = (nb_sectors >> 32) & 0xff;

            outbuf[4] = (nb_sectors >> 24) & 0xff;

            outbuf[5] = (nb_sectors >> 16) & 0xff;

            outbuf[6] = (nb_sectors >> 8) & 0xff;

            outbuf[7] = nb_sectors & 0xff;

            outbuf[8] = 0;

            outbuf[9] = 0;

            outbuf[10] = s->cluster_size * 2;

            outbuf[11] = 0;

            outbuf[12] = 0;

            outbuf[13] = get_physical_block_exp(&s->qdev.conf);

            /* set TPE bit if the format supports discard */

            if (s->qdev.conf.discard_granularity) {

                outbuf[14] = 0x80;

            }

            /* Protection, exponent and lowest lba field left blank. */

            buflen = req->cmd.xfer;

            break;

        }

        DPRINTF("Unsupported Service Action In\n");

        goto illegal_request;

    case REPORT_LUNS:

        if (req->cmd.xfer < 16)

            goto illegal_request;

        memset(outbuf, 0, 16);

        outbuf[3] = 8;

        buflen = 16;

        break;

    case VERIFY:

        break;

    case REZERO_UNIT:

        DPRINTF("Rezero Unit\n");

        if (!bdrv_is_inserted(s->bs)) {

            goto not_ready;

        }

        break;

    default:

        goto illegal_request;

    }

    scsi_req_set_status(r, GOOD, NO_SENSE);

    return buflen;

not_ready:

    scsi_command_complete(r, CHECK_CONDITION, NOT_READY);

    return -1;

illegal_request:

    scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);

    return -1;

}


static int xen_init(MachineState *ms)

{

    xen_xc = xen_xc_interface_open(0, 0, 0);

    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {

        xen_be_printf(NULL, 0, "can't open xen interface\n");

    qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);

    global_state_set_optional();

    savevm_skip_configuration();

    savevm_skip_section_footers();

    return 0;


static void cpu_common_realizefn(DeviceState *dev, Error **errp)
{
    CPUState *cpu = CPU(dev);
    if (dev->hotplugged) {
        cpu_synchronize_post_init(cpu);
        cpu_resume(cpu);
    }
}


uint8_t sd_read_data(SDState *sd)

{

    /* TODO: Append CRCs */

    uint8_t ret;

    int io_len;

    if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable)

        return 0x00;

    if (sd->state != sd_sendingdata_state) {

        qemu_log_mask(LOG_GUEST_ERROR,

                      "sd_read_data: not in Sending-Data state\n");

        return 0x00;

    }

    if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))

        return 0x00;

    io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;

    switch (sd->current_cmd) {

    case 6:	/* CMD6:   SWITCH_FUNCTION */

        ret = sd->data[sd->data_offset ++];

        if (sd->data_offset >= 64)

            sd->state = sd_transfer_state;

        break;

    case 9:	/* CMD9:   SEND_CSD */

    case 10:	/* CMD10:  SEND_CID */

        ret = sd->data[sd->data_offset ++];

        if (sd->data_offset >= 16)

            sd->state = sd_transfer_state;

        break;

    case 11:	/* CMD11:  READ_DAT_UNTIL_STOP */

        if (sd->data_offset == 0)

            BLK_READ_BLOCK(sd->data_start, io_len);

        ret = sd->data[sd->data_offset ++];

        if (sd->data_offset >= io_len) {

            sd->data_start += io_len;

            sd->data_offset = 0;

            if (sd->data_start + io_len > sd->size) {

                sd->card_status |= ADDRESS_ERROR;

                break;

            }

        }

        break;

    case 13:	/* ACMD13: SD_STATUS */

        ret = sd->sd_status[sd->data_offset ++];

        if (sd->data_offset >= sizeof(sd->sd_status))

            sd->state = sd_transfer_state;

        break;

    case 17:	/* CMD17:  READ_SINGLE_BLOCK */

        if (sd->data_offset == 0)

            BLK_READ_BLOCK(sd->data_start, io_len);

        ret = sd->data[sd->data_offset ++];

        if (sd->data_offset >= io_len)

            sd->state = sd_transfer_state;

        break;

    case 18:	/* CMD18:  READ_MULTIPLE_BLOCK */

        if (sd->data_offset == 0)

            BLK_READ_BLOCK(sd->data_start, io_len);

        ret = sd->data[sd->data_offset ++];

        if (sd->data_offset >= io_len) {

            sd->data_start += io_len;

            sd->data_offset = 0;

            if (sd->multi_blk_cnt != 0) {

                if (--sd->multi_blk_cnt == 0) {

                    /* Stop! */

                    sd->state = sd_transfer_state;

                    break;

                }

            }

            if (sd->data_start + io_len > sd->size) {

                sd->card_status |= ADDRESS_ERROR;

                break;

            }

        }

        break;

    case 22:	/* ACMD22: SEND_NUM_WR_BLOCKS */

        ret = sd->data[sd->data_offset ++];

        if (sd->data_offset >= 4)

            sd->state = sd_transfer_state;

        break;

    case 30:	/* CMD30:  SEND_WRITE_PROT */

        ret = sd->data[sd->data_offset ++];

        if (sd->data_offset >= 4)

            sd->state = sd_transfer_state;

        break;

    case 51:	/* ACMD51: SEND_SCR */

        ret = sd->scr[sd->data_offset ++];

        if (sd->data_offset >= sizeof(sd->scr))

            sd->state = sd_transfer_state;

        break;

    case 56:	/* CMD56:  GEN_CMD */

        if (sd->data_offset == 0)

            APP_READ_BLOCK(sd->data_start, sd->blk_len);

        ret = sd->data[sd->data_offset ++];

        if (sd->data_offset >= sd->blk_len)

            sd->state = sd_transfer_state;

        break;

    default:

        qemu_log_mask(LOG_GUEST_ERROR, "sd_read_data: unknown command\n");

        return 0x00;

    }

    return ret;

}


static av_always_inline int sbr_hf_apply_noise(int (*Y)[2],

                                                const SoftFloat *s_m,

                                                const SoftFloat *q_filt,

                                                int noise,

                                                int phi_sign0,

                                                int phi_sign1,

                                                int m_max)

{

    int m;

    for (m = 0; m < m_max; m++) {

        int y0 = Y[m][0];

        int y1 = Y[m][1];

        noise = (noise + 1) & 0x1ff;

        if (s_m[m].mant) {

            int shift, round;

            shift = 22 - s_m[m].exp;

            if (shift < 1) {

                av_log(NULL, AV_LOG_ERROR, "Overflow in sbr_hf_apply_noise, shift=%d\n", shift);

                return AVERROR(ERANGE);

            } else if (shift < 30) {

                round = 1 << (shift-1);

                y0 += (s_m[m].mant * phi_sign0 + round) >> shift;

                y1 += (s_m[m].mant * phi_sign1 + round) >> shift;

            }

        } else {

            int shift, round, tmp;

            int64_t accu;

            shift = 22 - q_filt[m].exp;

            if (shift < 1) {

                av_log(NULL, AV_LOG_ERROR, "Overflow in sbr_hf_apply_noise, shift=%d\n", shift);

                return AVERROR(ERANGE);

            } else if (shift < 30) {

                round = 1 << (shift-1);

                accu = (int64_t)q_filt[m].mant * ff_sbr_noise_table_fixed[noise][0];

                tmp = (int)((accu + 0x40000000) >> 31);

                y0 += (tmp + round) >> shift;

                accu = (int64_t)q_filt[m].mant * ff_sbr_noise_table_fixed[noise][1];

                tmp = (int)((accu + 0x40000000) >> 31);

                y1 += (tmp + round) >> shift;

            }

        }

        Y[m][0] = y0;

        Y[m][1] = y1;

        phi_sign1 = -phi_sign1;

    }

    return 0;

}


int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl,

                                const H2645NAL *nal)

{

    int i, j, ret = 0;

    int first_slice = sl == h->slice_ctx && !h->current_slice;

    ret = h264_slice_header_parse(h, sl, nal);

    if (ret < 0)

        return ret;

    if (sl->first_mb_addr == 0) { // FIXME better field boundary detection

        if (h->current_slice) {

            if (h->setup_finished) {

                av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n");

                return AVERROR_INVALIDDATA;

            }

            if (h->max_contexts > 1) {

                if (!h->single_decode_warning) {

                    av_log(h->avctx, AV_LOG_WARNING, "Cannot decode multiple access units as slice threads\n");

                    h->single_decode_warning = 1;

                }

                h->max_contexts = 1;

                return SLICE_SINGLETHREAD;

            }

            if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) {

                ret = ff_h264_field_end(h, h->slice_ctx, 1);

                h->current_slice = 0;

                if (ret < 0)

                    return ret;

            } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type  == NAL_IDR_SLICE) {

                av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n");

                ret = ff_h264_field_end(h, h->slice_ctx, 1);

                h->current_slice = 0;

                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0);

                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1);

                h->cur_pic_ptr = NULL;

                if (ret < 0)

                    return ret;

            } else

                return AVERROR_INVALIDDATA;

        }

        if (!h->first_field) {

            if (h->cur_pic_ptr && !h->droppable) {

                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,

                                          h->picture_structure == PICT_BOTTOM_FIELD);

            }

            h->cur_pic_ptr = NULL;

        }

    }

    if (!h->current_slice)

        av_assert0(sl == h->slice_ctx);

    if (h->current_slice == 0 && !h->first_field) {

        if (

            (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) ||

            (h->avctx->skip_frame >= AVDISCARD_BIDIR  && sl->slice_type_nos == AV_PICTURE_TYPE_B) ||

            (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) ||

            (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) ||

            h->avctx->skip_frame >= AVDISCARD_ALL) {

            return SLICE_SKIPED;

        }

    }

    if (!first_slice) {

        const PPS *pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;

        if (h->ps.pps->sps_id != pps->sps_id ||

            h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*||

            (h->setup_finished && h->ps.pps != pps)*/) {

            av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");

            return AVERROR_INVALIDDATA;

        }

        if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {

            av_log(h->avctx, AV_LOG_ERROR,

               "SPS changed in the middle of the frame\n");

            return AVERROR_INVALIDDATA;

        }

    }

    if (h->current_slice == 0) {

        ret = h264_field_start(h, sl, nal, first_slice);

        if (ret < 0)

            return ret;

    } else {

        if (h->picture_structure != sl->picture_structure ||

            h->droppable         != (nal->ref_idc == 0)) {

            av_log(h->avctx, AV_LOG_ERROR,

                   "Changing field mode (%d -> %d) between slices is not allowed\n",

                   h->picture_structure, sl->picture_structure);

            return AVERROR_INVALIDDATA;

        } else if (!h->cur_pic_ptr) {

            av_log(h->avctx, AV_LOG_ERROR,

                   "unset cur_pic_ptr on slice %d\n",

                   h->current_slice + 1);

            return AVERROR_INVALIDDATA;

        }

    }

    av_assert1(h->mb_num == h->mb_width * h->mb_height);

    if (sl->first_mb_addr << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num ||

        sl->first_mb_addr >= h->mb_num) {

        av_log(h->avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n");

        return AVERROR_INVALIDDATA;

    }

    sl->resync_mb_x = sl->mb_x =  sl->first_mb_addr % h->mb_width;

    sl->resync_mb_y = sl->mb_y = (sl->first_mb_addr / h->mb_width) <<

                                 FIELD_OR_MBAFF_PICTURE(h);

    if (h->picture_structure == PICT_BOTTOM_FIELD)

        sl->resync_mb_y = sl->mb_y = sl->mb_y + 1;

    av_assert1(sl->mb_y < h->mb_height);

    if (!h->setup_finished) {

        ff_h264_init_poc(h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc,

                         h->ps.sps, &h->poc, h->picture_structure, nal->ref_idc);

        memcpy(h->mmco, sl->mmco, sl->nb_mmco * sizeof(*h->mmco));

        h->nb_mmco = sl->nb_mmco;

        h->explicit_ref_marking = sl->explicit_ref_marking;

    }

    ret = ff_h264_build_ref_list(h, sl);

    if (ret < 0)

        return ret;

    if (h->ps.pps->weighted_bipred_idc == 2 &&

        sl->slice_type_nos == AV_PICTURE_TYPE_B) {

        implicit_weight_table(h, sl, -1);

        if (FRAME_MBAFF(h)) {

            implicit_weight_table(h, sl, 0);

            implicit_weight_table(h, sl, 1);

        }

    }

    if (sl->slice_type_nos == AV_PICTURE_TYPE_B && !sl->direct_spatial_mv_pred)

        ff_h264_direct_dist_scale_factor(h, sl);

    ff_h264_direct_ref_list_init(h, sl);

    if (h->avctx->skip_loop_filter >= AVDISCARD_ALL ||

        (h->avctx->skip_loop_filter >= AVDISCARD_NONKEY &&

         h->nal_unit_type != NAL_IDR_SLICE) ||

        (h->avctx->skip_loop_filter >= AVDISCARD_NONINTRA &&

         sl->slice_type_nos != AV_PICTURE_TYPE_I) ||

        (h->avctx->skip_loop_filter >= AVDISCARD_BIDIR  &&

         sl->slice_type_nos == AV_PICTURE_TYPE_B) ||

        (h->avctx->skip_loop_filter >= AVDISCARD_NONREF &&

         nal->ref_idc == 0))

        sl->deblocking_filter = 0;

    if (sl->deblocking_filter == 1 && h->max_contexts > 1) {

        if (h->avctx->flags2 & AV_CODEC_FLAG2_FAST) {

            /* Cheat slightly for speed:

             * Do not bother to deblock across slices. */

            sl->deblocking_filter = 2;

        } else {

            h->postpone_filter = 1;

        }

    }

    sl->qp_thresh = 15 -

                   FFMIN(sl->slice_alpha_c0_offset, sl->slice_beta_offset) -

                   FFMAX3(0,

                          h->ps.pps->chroma_qp_index_offset[0],

                          h->ps.pps->chroma_qp_index_offset[1]) +

                   6 * (h->ps.sps->bit_depth_luma - 8);

    sl->slice_num       = ++h->current_slice;

    if (sl->slice_num)

        h->slice_row[(sl->slice_num-1)&(MAX_SLICES-1)]= sl->resync_mb_y;

    if (   h->slice_row[sl->slice_num&(MAX_SLICES-1)] + 3 >= sl->resync_mb_y

        && h->slice_row[sl->slice_num&(MAX_SLICES-1)] <= sl->resync_mb_y

        && sl->slice_num >= MAX_SLICES) {

        //in case of ASO this check needs to be updated depending on how we decide to assign slice numbers in this case

        av_log(h->avctx, AV_LOG_WARNING, "Possibly too many slices (%d >= %d), increase MAX_SLICES and recompile if there are artifacts\n", sl->slice_num, MAX_SLICES);

    }

    for (j = 0; j < 2; j++) {

        int id_list[16];

        int *ref2frm = h->ref2frm[sl->slice_num & (MAX_SLICES - 1)][j];

        for (i = 0; i < 16; i++) {

            id_list[i] = 60;

            if (j < sl->list_count && i < sl->ref_count[j] &&

                sl->ref_list[j][i].parent->f->buf[0]) {

                int k;

                AVBuffer *buf = sl->ref_list[j][i].parent->f->buf[0]->buffer;

                for (k = 0; k < h->short_ref_count; k++)

                    if (h->short_ref[k]->f->buf[0]->buffer == buf) {

                        id_list[i] = k;

                        break;

                    }

                for (k = 0; k < h->long_ref_count; k++)

                    if (h->long_ref[k] && h->long_ref[k]->f->buf[0]->buffer == buf) {

                        id_list[i] = h->short_ref_count + k;

                        break;

                    }

            }

        }

        ref2frm[0] =

        ref2frm[1] = -1;

        for (i = 0; i < 16; i++)

            ref2frm[i + 2] = 4 * id_list[i] + (sl->ref_list[j][i].reference & 3);

        ref2frm[18 + 0] =

        ref2frm[18 + 1] = -1;

        for (i = 16; i < 48; i++)

            ref2frm[i + 4] = 4 * id_list[(i - 16) >> 1] +

                             (sl->ref_list[j][i].reference & 3);

    }

    if (h->avctx->debug & FF_DEBUG_PICT_INFO) {

        av_log(h->avctx, AV_LOG_DEBUG,

               "slice:%d %s mb:%d %c%s%s frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n",

               sl->slice_num,

               (h->picture_structure == PICT_FRAME ? "F" : h->picture_structure == PICT_TOP_FIELD ? "T" : "B"),

               sl->mb_y * h->mb_width + sl->mb_x,

               av_get_picture_type_char(sl->slice_type),

               sl->slice_type_fixed ? " fix" : "",

               nal->type == NAL_IDR_SLICE ? " IDR" : "",

               h->poc.frame_num,

               h->cur_pic_ptr->field_poc[0],

               h->cur_pic_ptr->field_poc[1],

               sl->ref_count[0], sl->ref_count[1],

               sl->qscale,

               sl->deblocking_filter,

               sl->slice_alpha_c0_offset, sl->slice_beta_offset,

               sl->pwt.use_weight,

               sl->pwt.use_weight == 1 && sl->pwt.use_weight_chroma ? "c" : "",

               sl->slice_type == AV_PICTURE_TYPE_B ? (sl->direct_spatial_mv_pred ? "SPAT" : "TEMP") : "");

    }

    return 0;

}


static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,

                            const DXVA_PicParams_H264 *pp, unsigned position, unsigned size)

{

    const H264Context *h = avctx->priv_data;

    H264SliceContext *sl = &h->slice_ctx[0];

    AVDXVAContext *ctx = avctx->hwaccel_context;

    unsigned list;

    memset(slice, 0, sizeof(*slice));

    slice->BSNALunitDataLocation = position;

    slice->SliceBytesInBuffer    = size;

    slice->wBadSliceChopping     = 0;

    slice->first_mb_in_slice     = (sl->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + sl->mb_x;

    slice->NumMbsForSlice        = 0; /* XXX it is set once we have all slices */

    slice->BitOffsetToSliceData  = get_bits_count(&sl->gb) - 8;

    slice->slice_type            = ff_h264_get_slice_type(sl);

    if (sl->slice_type_fixed)

        slice->slice_type += 5;

    slice->luma_log2_weight_denom       = sl->pwt.luma_log2_weight_denom;

    slice->chroma_log2_weight_denom     = sl->pwt.chroma_log2_weight_denom;

    if (sl->list_count > 0)

        slice->num_ref_idx_l0_active_minus1 = sl->ref_count[0] - 1;

    if (sl->list_count > 1)

        slice->num_ref_idx_l1_active_minus1 = sl->ref_count[1] - 1;

    slice->slice_alpha_c0_offset_div2   = sl->slice_alpha_c0_offset / 2;

    slice->slice_beta_offset_div2       = sl->slice_beta_offset     / 2;

    slice->Reserved8Bits                = 0;

    for (list = 0; list < 2; list++) {

        unsigned i;

        for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) {

            if (list < sl->list_count && i < sl->ref_count[list]) {

                const H264Picture *r = sl->ref_list[list][i].parent;

                unsigned plane;

                unsigned index;

                if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)

                    index = ff_dxva2_get_surface_index(avctx, ctx, r->f);

                else

                    index = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, r->f));

                fill_picture_entry(&slice->RefPicList[list][i], index,

                                   sl->ref_list[list][i].reference == PICT_BOTTOM_FIELD);

                for (plane = 0; plane < 3; plane++) {

                    int w, o;

                    if (plane == 0 && sl->pwt.luma_weight_flag[list]) {

                        w = sl->pwt.luma_weight[i][list][0];

                        o = sl->pwt.luma_weight[i][list][1];

                    } else if (plane >= 1 && sl->pwt.chroma_weight_flag[list]) {

                        w = sl->pwt.chroma_weight[i][list][plane-1][0];

                        o = sl->pwt.chroma_weight[i][list][plane-1][1];

                    } else {

                        w = 1 << (plane == 0 ? sl->pwt.luma_log2_weight_denom :

                                               sl->pwt.chroma_log2_weight_denom);

                        o = 0;

                    }

                    slice->Weights[list][i][plane][0] = w;

                    slice->Weights[list][i][plane][1] = o;

                }

            } else {

                unsigned plane;

                slice->RefPicList[list][i].bPicEntry = 0xff;

                for (plane = 0; plane < 3; plane++) {

                    slice->Weights[list][i][plane][0] = 0;

                    slice->Weights[list][i][plane][1] = 0;

                }

            }

        }

    }

    slice->slice_qs_delta    = 0; /* XXX not implemented by FFmpeg */

    slice->slice_qp_delta    = sl->qscale - h->ps.pps->init_qp;

    slice->redundant_pic_cnt = sl->redundant_pic_count;

    if (sl->slice_type == AV_PICTURE_TYPE_B)

        slice->direct_spatial_mv_pred_flag = sl->direct_spatial_mv_pred;

    slice->cabac_init_idc = h->ps.pps->cabac ? sl->cabac_init_idc : 0;

    if (sl->deblocking_filter < 2)

        slice->disable_deblocking_filter_idc = 1 - sl->deblocking_filter;

    else

        slice->disable_deblocking_filter_idc = sl->deblocking_filter;

    slice->slice_id = h->current_slice - 1;

}


static int dvdsub_parse(AVCodecParserContext *s,

                        AVCodecContext *avctx,

                        const uint8_t **poutbuf, int *poutbuf_size,

                        const uint8_t *buf, int buf_size)

{

    DVDSubParseContext *pc = s->priv_data;

    if (pc->packet_index == 0) {

        if (buf_size < 2)

            return buf_size;

        pc->packet_len = AV_RB16(buf);

        if (pc->packet_len == 0) /* HD-DVD subpicture packet */

            pc->packet_len = AV_RB32(buf+2);

        av_freep(&pc->packet);

        pc->packet = av_malloc(pc->packet_len);

    }

    if (pc->packet) {

        if (pc->packet_index + buf_size <= pc->packet_len) {

            memcpy(pc->packet + pc->packet_index, buf, buf_size);

            pc->packet_index += buf_size;

            if (pc->packet_index >= pc->packet_len) {

                *poutbuf = pc->packet;

                *poutbuf_size = pc->packet_len;

                pc->packet_index = 0;

                return buf_size;

            }

        } else {

            /* erroneous size */

            pc->packet_index = 0;

        }

    }

    *poutbuf = NULL;

    *poutbuf_size = 0;

    return buf_size;

}


static int kmvc_decode_inter_8x8(KmvcContext * ctx, int w, int h)

{

    BitBuf bb;

    int res, val;

    int i, j;

    int bx, by;

    int l0x, l1x, l0y, l1y;

    int mx, my;

    kmvc_init_getbits(bb, &ctx->g);

    for (by = 0; by < h; by += 8)

        for (bx = 0; bx < w; bx += 8) {

            kmvc_getbit(bb, &ctx->g, res);

            if (!res) {

                kmvc_getbit(bb, &ctx->g, res);

                if (!res) {     // fill whole 8x8 block

                    if (!bytestream2_get_bytes_left(&ctx->g)) {

                        av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n");

                        return AVERROR_INVALIDDATA;

                    }

                    val = bytestream2_get_byte(&ctx->g);

                    for (i = 0; i < 64; i++)

                        BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val;

                } else {        // copy block from previous frame

                    for (i = 0; i < 64; i++)

                        BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) =

                            BLK(ctx->prev, bx + (i & 0x7), by + (i >> 3));

                }

            } else {            // handle four 4x4 subblocks

                if (!bytestream2_get_bytes_left(&ctx->g)) {

                    av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n");

                    return AVERROR_INVALIDDATA;

                }

                for (i = 0; i < 4; i++) {

                    l0x = bx + (i & 1) * 4;

                    l0y = by + (i & 2) * 2;

                    kmvc_getbit(bb, &ctx->g, res);

                    if (!res) {

                        kmvc_getbit(bb, &ctx->g, res);

                        if (!res) {     // fill whole 4x4 block

                            val = bytestream2_get_byte(&ctx->g);

                            for (j = 0; j < 16; j++)

                                BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val;

                        } else {        // copy block

                            val = bytestream2_get_byte(&ctx->g);

                            mx = (val & 0xF) - 8;

                            my = (val >> 4) - 8;

                            if ((l0x+mx) + 320*(l0y+my) < 0 || (l0x+mx) + 320*(l0y+my) > 318*198) {

                                av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n");

                                return AVERROR_INVALIDDATA;

                            }

                            for (j = 0; j < 16; j++)

                                BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) =

                                    BLK(ctx->prev, l0x + (j & 3) + mx, l0y + (j >> 2) + my);

                        }

                    } else {    // descend to 2x2 sub-sub-blocks

                        for (j = 0; j < 4; j++) {

                            l1x = l0x + (j & 1) * 2;

                            l1y = l0y + (j & 2);

                            kmvc_getbit(bb, &ctx->g, res);

                            if (!res) {

                                kmvc_getbit(bb, &ctx->g, res);

                                if (!res) {     // fill whole 2x2 block

                                    val = bytestream2_get_byte(&ctx->g);

                                    BLK(ctx->cur, l1x, l1y) = val;

                                    BLK(ctx->cur, l1x + 1, l1y) = val;

                                    BLK(ctx->cur, l1x, l1y + 1) = val;

                                    BLK(ctx->cur, l1x + 1, l1y + 1) = val;

                                } else {        // copy block

                                    val = bytestream2_get_byte(&ctx->g);

                                    mx = (val & 0xF) - 8;

                                    my = (val >> 4) - 8;

                                    if ((l1x+mx) + 320*(l1y+my) < 0 || (l1x+mx) + 320*(l1y+my) > 318*198) {

                                        av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n");

                                        return AVERROR_INVALIDDATA;

                                    }

                                    BLK(ctx->cur, l1x, l1y) = BLK(ctx->prev, l1x + mx, l1y + my);

                                    BLK(ctx->cur, l1x + 1, l1y) =

                                        BLK(ctx->prev, l1x + 1 + mx, l1y + my);

                                    BLK(ctx->cur, l1x, l1y + 1) =

                                        BLK(ctx->prev, l1x + mx, l1y + 1 + my);

                                    BLK(ctx->cur, l1x + 1, l1y + 1) =

                                        BLK(ctx->prev, l1x + 1 + mx, l1y + 1 + my);

                                }

                            } else {    // read values for block

                                BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g);

                                BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g);

                                BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g);

                                BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g);

                            }

                        }

                    }

                }

            }

        }

    return 0;

}


static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header)

{

    OMAContext *oc = s->priv_data;

    ID3v2ExtraMetaGEOB *geob = NULL;

    uint8_t *gdata;

    oc->encrypted = 1;

    av_log(s, AV_LOG_INFO, "File is encrypted\n");

    /* find GEOB metadata */

    while (em) {

        if (!strcmp(em->tag, "GEOB") &&

            (geob = em->data) &&

            (!strcmp(geob->description, "OMG_LSI") ||

             !strcmp(geob->description, "OMG_BKLSI"))) {

            break;

        }

        em = em->next;

    }

    if (!em) {

        av_log(s, AV_LOG_ERROR, "No encryption header found\n");

        return -1;

    }

    if (geob->datasize < 64) {

        av_log(s, AV_LOG_ERROR, "Invalid GEOB data size: %u\n", geob->datasize);

        return -1;

    }

    gdata = geob->data;

    if (AV_RB16(gdata) != 1)

        av_log(s, AV_LOG_WARNING, "Unknown version in encryption header\n");

    oc->k_size = AV_RB16(&gdata[2]);

    oc->e_size = AV_RB16(&gdata[4]);

    oc->i_size = AV_RB16(&gdata[6]);

    oc->s_size = AV_RB16(&gdata[8]);

    if (memcmp(&gdata[OMA_ENC_HEADER_SIZE], "KEYRING     ", 12)) {

        av_log(s, AV_LOG_ERROR, "Invalid encryption header\n");

        return -1;

    }

    if (oc->k_size + oc->e_size + oc->i_size > geob->datasize) {

        av_log(s, AV_LOG_ERROR, "Too little GEOB data\n");

        return AVERROR_INVALIDDATA;

    }

    oc->rid = AV_RB32(&gdata[OMA_ENC_HEADER_SIZE + 28]);

    av_log(s, AV_LOG_DEBUG, "RID: %.8x\n", oc->rid);

    memcpy(oc->iv, &header[0x58], 8);

    hex_log(s, AV_LOG_DEBUG, "IV", oc->iv, 8);

    hex_log(s, AV_LOG_DEBUG, "CBC-MAC", &gdata[OMA_ENC_HEADER_SIZE+oc->k_size+oc->e_size+oc->i_size], 8);

    if (s->keylen > 0) {

        kset(s, s->key, s->key, s->keylen);

    }

    if (!memcmp(oc->r_val, (const uint8_t[8]){0}, 8) ||

        rprobe(s, gdata, oc->r_val) < 0 &&

        nprobe(s, gdata, geob->datasize, oc->n_val) < 0) {

        int i;

        for (i = 0; i < FF_ARRAY_ELEMS(leaf_table); i += 2) {

            uint8_t buf[16];

            AV_WL64(buf, leaf_table[i]);

            AV_WL64(&buf[8], leaf_table[i+1]);

            kset(s, buf, buf, 16);

            if (!rprobe(s, gdata, oc->r_val) || !nprobe(s, gdata, geob->datasize, oc->n_val))

                break;

        }

        if (i >= FF_ARRAY_ELEMS(leaf_table)) {

            av_log(s, AV_LOG_ERROR, "Invalid key\n");

            return -1;

        }

    }

    /* e_val */

    av_des_init(&oc->av_des, oc->m_val, 64, 0);

    av_des_crypt(&oc->av_des, oc->e_val, &gdata[OMA_ENC_HEADER_SIZE + 40], 1, NULL, 0);

    hex_log(s, AV_LOG_DEBUG, "EK", oc->e_val, 8);

    /* init e_val */

    av_des_init(&oc->av_des, oc->e_val, 64, 1);

    return 0;

}


uint32_t avpriv_fmt_ff2v4l(enum AVPixelFormat pix_fmt, enum AVCodecID codec_id)

{

    int i;

    for (i = 0; avpriv_fmt_conversion_table[i].codec_id != AV_CODEC_ID_NONE; i++) {

        if ((codec_id == AV_CODEC_ID_NONE ||

             avpriv_fmt_conversion_table[i].codec_id == codec_id) &&

            (pix_fmt == AV_PIX_FMT_NONE ||

             avpriv_fmt_conversion_table[i].ff_fmt == pix_fmt)) {

            return avpriv_fmt_conversion_table[i].v4l2_fmt;

        }

    }

    return 0;

}


int avfilter_default_config_output_link(AVFilterLink *link)

{

    if (link->src->input_count && link->src->inputs[0]) {

        if (link->type == AVMEDIA_TYPE_VIDEO) {

            link->w = link->src->inputs[0]->w;

            link->h = link->src->inputs[0]->h;

            link->time_base = link->src->inputs[0]->time_base;

        } else if (link->type == AVMEDIA_TYPE_AUDIO) {

            link->channel_layout = link->src->inputs[0]->channel_layout;

            link->sample_rate    = link->src->inputs[0]->sample_rate;

        }

    } else {

        /* XXX: any non-simple filter which would cause this branch to be taken

         * really should implement its own config_props() for this link. */

        return -1;

    }

    return 0;

}


static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags)

{

    MOVStreamContext *sc = st->priv_data;

    int sample, time_sample;

    int i;

    sample = av_index_search_timestamp(st, timestamp, flags);

    dprintf(st->codec, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);

    if (sample < 0) /* not sure what to do */

        return -1;

    sc->current_sample = sample;

    dprintf(st->codec, "stream %d, found sample %d\n", st->index, sc->current_sample);

    /* adjust ctts index */

    if (sc->ctts_data) {

        time_sample = 0;

        for (i = 0; i < sc->ctts_count; i++) {

            time_sample += sc->ctts_data[i].count;

            if (time_sample >= sc->current_sample) {

                sc->sample_to_ctime_index = i;

                sc->sample_to_ctime_sample = time_sample - sc->current_sample;

                break;

            }

        }

    }

    return sample;

}


static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr,

                        AVPacket *avpkt)

{

    const uint8_t *buf  = avpkt->data;

    int buf_size        = avpkt->size;

    MPADecodeContext *s = avctx->priv_data;

    uint32_t header;

    int ret;

    int skipped = 0;

    while(buf_size && !*buf){

        buf++;

        buf_size--;

        skipped++;

    }

    if (buf_size < HEADER_SIZE)

        return AVERROR_INVALIDDATA;

    header = AV_RB32(buf);

    if (header>>8 == AV_RB32("TAG")>>8) {

        av_log(avctx, AV_LOG_DEBUG, "discarding ID3 tag\n");

        return buf_size;

    }

    ret = avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header);

    if (ret < 0) {

        av_log(avctx, AV_LOG_ERROR, "Header missing\n");

        return AVERROR_INVALIDDATA;

    } else if (ret == 1) {

        /* free format: prepare to compute frame size */

        s->frame_size = -1;

        return AVERROR_INVALIDDATA;

    }

    /* update codec info */

    avctx->channels       = s->nb_channels;

    avctx->channel_layout = s->nb_channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;

    if (!avctx->bit_rate)

        avctx->bit_rate = s->bit_rate;

    if (s->frame_size <= 0) {

        av_log(avctx, AV_LOG_ERROR, "incomplete frame\n");

        return AVERROR_INVALIDDATA;

    } else if (s->frame_size < buf_size) {

        av_log(avctx, AV_LOG_DEBUG, "incorrect frame size - multiple frames in buffer?\n");

        buf_size= s->frame_size;

    }

    s->frame = data;

    ret = mp_decode_frame(s, NULL, buf, buf_size);

    if (ret >= 0) {

        s->frame->nb_samples = avctx->frame_size;

        *got_frame_ptr       = 1;

        avctx->sample_rate   = s->sample_rate;

        //FIXME maybe move the other codec info stuff from above here too

    } else {

        av_log(avctx, AV_LOG_ERROR, "Error while decoding MPEG audio frame.\n");

        /* Only return an error if the bad frame makes up the whole packet or

         * the error is related to buffer management.

         * If there is more data in the packet, just consume the bad frame

         * instead of returning an error, which would discard the whole

         * packet. */

        *got_frame_ptr = 0;

        if (buf_size == avpkt->size || ret != AVERROR_INVALIDDATA)

            return ret;

    }

    s->frame_size = 0;

    return buf_size + skipped;

}


bool arp_table_search(Slirp *slirp, uint32_t ip_addr,

                      uint8_t out_ethaddr[ETH_ALEN])

{

    const uint32_t broadcast_addr =

        ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;

    ArpTable *arptbl = &slirp->arp_table;

    int i;

    DEBUG_CALL("arp_table_search");

    DEBUG_ARG("ip = 0x%x", ip_addr);

    /* Check 0.0.0.0/8 invalid source-only addresses */

    assert((ip_addr & htonl(~(0xf << 28))) != 0);

    /* If broadcast address */

    if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {

        /* return Ethernet broadcast address */

        memset(out_ethaddr, 0xff, ETH_ALEN);

        return 1;

    }

    for (i = 0; i < ARP_TABLE_SIZE; i++) {

        if (arptbl->table[i].ar_sip == ip_addr) {

            memcpy(out_ethaddr, arptbl->table[i].ar_sha,  ETH_ALEN);

            DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",

                        out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],

                        out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));

            return 1;

        }

    }

    return 0;

}


void smc91c111_init(NICInfo *nd, uint32_t base, void *pic, int irq)

{

    smc91c111_state *s;

    int iomemtype;

    s = (smc91c111_state *)qemu_mallocz(sizeof(smc91c111_state));

    iomemtype = cpu_register_io_memory(0, smc91c111_readfn,

                                       smc91c111_writefn, s);

    cpu_register_physical_memory(base, 16, iomemtype);

    s->base = base;

    s->pic = pic;

    s->irq = irq;

    memcpy(s->macaddr, nd->macaddr, 6);

    smc91c111_reset(s);

    s->vc = qemu_new_vlan_client(nd->vlan, smc91c111_receive, s);

    /* ??? Save/restore.  */

}


void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64],

                        int motion_x, int motion_y)

{

    int cbpc, cbpy, pred_x, pred_y;

    PutBitContext *const pb2    = s->data_partitioning ? &s->pb2 : &s->pb;

    PutBitContext *const tex_pb = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_B ? &s->tex_pb : &s->pb;

    PutBitContext *const dc_pb  = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_I ? &s->pb2 : &s->pb;

    const int interleaved_stats = (s->flags & CODEC_FLAG_PASS1) && !s->data_partitioning ? 1 : 0;

    if (!s->mb_intra) {

        int i, cbp;

        if (s->pict_type == AV_PICTURE_TYPE_B) {

            /* convert from mv_dir to type */

            static const int mb_type_table[8] = { -1, 3, 2, 1, -1, -1, -1, 0 };

            int mb_type = mb_type_table[s->mv_dir];

            if (s->mb_x == 0) {

                for (i = 0; i < 2; i++)

                    s->last_mv[i][0][0] =

                    s->last_mv[i][0][1] =

                    s->last_mv[i][1][0] =

                    s->last_mv[i][1][1] = 0;

            }

            assert(s->dquant >= -2 && s->dquant <= 2);

            assert((s->dquant & 1) == 0);

            assert(mb_type >= 0);

            /* nothing to do if this MB was skipped in the next P Frame */

            if (s->next_picture.mbskip_table[s->mb_y * s->mb_stride + s->mb_x]) {  // FIXME avoid DCT & ...

                s->skip_count++;

                s->mv[0][0][0] =

                s->mv[0][0][1] =

                s->mv[1][0][0] =

                s->mv[1][0][1] = 0;

                s->mv_dir  = MV_DIR_FORWARD;  // doesn't matter

                s->qscale -= s->dquant;

//                s->mb_skipped = 1;

                return;

            }

            cbp = get_b_cbp(s, block, motion_x, motion_y, mb_type);

            if ((cbp | motion_x | motion_y | mb_type) == 0) {

                /* direct MB with MV={0,0} */

                assert(s->dquant == 0);

                put_bits(&s->pb, 1, 1); /* mb not coded modb1=1 */

                if (interleaved_stats) {

                    s->misc_bits++;

                    s->last_bits++;

                }

                s->skip_count++;

                return;

            }

            put_bits(&s->pb, 1, 0);            /* mb coded modb1=0 */

            put_bits(&s->pb, 1, cbp ? 0 : 1);  /* modb2 */ // FIXME merge

            put_bits(&s->pb, mb_type + 1, 1);  // this table is so simple that we don't need it :)

            if (cbp)

                put_bits(&s->pb, 6, cbp);

            if (cbp && mb_type) {

                if (s->dquant)

                    put_bits(&s->pb, 2, (s->dquant >> 2) + 3);

                else

                    put_bits(&s->pb, 1, 0);

            } else

                s->qscale -= s->dquant;

            if (!s->progressive_sequence) {

                if (cbp)

                    put_bits(&s->pb, 1, s->interlaced_dct);

                if (mb_type)                  // not direct mode

                    put_bits(&s->pb, 1, s->mv_type == MV_TYPE_FIELD);

            }

            if (interleaved_stats)

                s->misc_bits += get_bits_diff(s);

            if (!mb_type) {

                assert(s->mv_dir & MV_DIRECT);

                ff_h263_encode_motion_vector(s, motion_x, motion_y, 1);

                s->b_count++;

                s->f_count++;

            } else {

                assert(mb_type > 0 && mb_type < 4);

                if (s->mv_type != MV_TYPE_FIELD) {

                    if (s->mv_dir & MV_DIR_FORWARD) {

                        ff_h263_encode_motion_vector(s,

                                                     s->mv[0][0][0] - s->last_mv[0][0][0],

                                                     s->mv[0][0][1] - s->last_mv[0][0][1],

                                                     s->f_code);

                        s->last_mv[0][0][0] =

                        s->last_mv[0][1][0] = s->mv[0][0][0];

                        s->last_mv[0][0][1] =

                        s->last_mv[0][1][1] = s->mv[0][0][1];

                        s->f_count++;

                    }

                    if (s->mv_dir & MV_DIR_BACKWARD) {

                        ff_h263_encode_motion_vector(s,

                                                     s->mv[1][0][0] - s->last_mv[1][0][0],

                                                     s->mv[1][0][1] - s->last_mv[1][0][1],

                                                     s->b_code);

                        s->last_mv[1][0][0] =

                        s->last_mv[1][1][0] = s->mv[1][0][0];

                        s->last_mv[1][0][1] =

                        s->last_mv[1][1][1] = s->mv[1][0][1];

                        s->b_count++;

                    }

                } else {

                    if (s->mv_dir & MV_DIR_FORWARD) {

                        put_bits(&s->pb, 1, s->field_select[0][0]);

                        put_bits(&s->pb, 1, s->field_select[0][1]);

                    }

                    if (s->mv_dir & MV_DIR_BACKWARD) {

                        put_bits(&s->pb, 1, s->field_select[1][0]);

                        put_bits(&s->pb, 1, s->field_select[1][1]);

                    }

                    if (s->mv_dir & MV_DIR_FORWARD) {

                        for (i = 0; i < 2; i++) {

                            ff_h263_encode_motion_vector(s,

                                                         s->mv[0][i][0] - s->last_mv[0][i][0],

                                                         s->mv[0][i][1] - s->last_mv[0][i][1] / 2,

                                                         s->f_code);

                            s->last_mv[0][i][0] = s->mv[0][i][0];

                            s->last_mv[0][i][1] = s->mv[0][i][1] * 2;

                        }

                        s->f_count++;

                    }

                    if (s->mv_dir & MV_DIR_BACKWARD) {

                        for (i = 0; i < 2; i++) {

                            ff_h263_encode_motion_vector(s,

                                                         s->mv[1][i][0] - s->last_mv[1][i][0],

                                                         s->mv[1][i][1] - s->last_mv[1][i][1] / 2,

                                                         s->b_code);

                            s->last_mv[1][i][0] = s->mv[1][i][0];

                            s->last_mv[1][i][1] = s->mv[1][i][1] * 2;

                        }

                        s->b_count++;

                    }

                }

            }

            if (interleaved_stats)

                s->mv_bits += get_bits_diff(s);

            mpeg4_encode_blocks(s, block, NULL, NULL, NULL, &s->pb);

            if (interleaved_stats)

                s->p_tex_bits += get_bits_diff(s);

        } else { /* s->pict_type==AV_PICTURE_TYPE_B */

            cbp = get_p_cbp(s, block, motion_x, motion_y);

            if ((cbp | motion_x | motion_y | s->dquant) == 0 &&

                s->mv_type == MV_TYPE_16X16) {

                /* check if the B frames can skip it too, as we must skip it

                 * if we skip here why didn't they just compress

                 * the skip-mb bits instead of reusing them ?! */

                if (s->max_b_frames > 0) {

                    int i;

                    int x, y, offset;

                    uint8_t *p_pic;

                    x = s->mb_x * 16;

                    y = s->mb_y * 16;

                    if (x + 16 > s->width)

                        x = s->width - 16;

                    if (y + 16 > s->height)

                        y = s->height - 16;

                    offset = x + y * s->linesize;

                    p_pic  = s->new_picture.f.data[0] + offset;

                    s->mb_skipped = 1;

                    for (i = 0; i < s->max_b_frames; i++) {

                        uint8_t *b_pic;

                        int diff;

                        Picture *pic = s->reordered_input_picture[i + 1];

                        if (!pic || pic->f.pict_type != AV_PICTURE_TYPE_B)

                            break;

                        b_pic = pic->f.data[0] + offset;

                        if (!pic->shared)

                            b_pic += INPLACE_OFFSET;

                        diff = s->dsp.sad[0](NULL, p_pic, b_pic, s->linesize, 16);

                        if (diff > s->qscale * 70) {  // FIXME check that 70 is optimal

                            s->mb_skipped = 0;

                            break;

                        }

                    }

                } else

                    s->mb_skipped = 1;

                if (s->mb_skipped == 1) {

                    /* skip macroblock */

                    put_bits(&s->pb, 1, 1);

                    if (interleaved_stats) {

                        s->misc_bits++;

                        s->last_bits++;

                    }

                    s->skip_count++;

                    return;

                }

            }

            put_bits(&s->pb, 1, 0);     /* mb coded */

            cbpc  = cbp & 3;

            cbpy  = cbp >> 2;

            cbpy ^= 0xf;

            if (s->mv_type == MV_TYPE_16X16) {

                if (s->dquant)

                    cbpc += 8;

                put_bits(&s->pb,

                         ff_h263_inter_MCBPC_bits[cbpc],

                         ff_h263_inter_MCBPC_code[cbpc]);

                put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]);

                if (s->dquant)

                    put_bits(pb2, 2, dquant_code[s->dquant + 2]);

                if (!s->progressive_sequence) {

                    if (cbp)

                        put_bits(pb2, 1, s->interlaced_dct);

                    put_bits(pb2, 1, 0);

                }

                if (interleaved_stats)

                    s->misc_bits += get_bits_diff(s);

                /* motion vectors: 16x16 mode */

                ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);

                ff_h263_encode_motion_vector(s,

                                             motion_x - pred_x,

                                             motion_y - pred_y,

                                             s->f_code);

            } else if (s->mv_type == MV_TYPE_FIELD) {

                if (s->dquant)

                    cbpc += 8;

                put_bits(&s->pb,

                         ff_h263_inter_MCBPC_bits[cbpc],

                         ff_h263_inter_MCBPC_code[cbpc]);

                put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]);

                if (s->dquant)

                    put_bits(pb2, 2, dquant_code[s->dquant + 2]);

                assert(!s->progressive_sequence);

                if (cbp)

                    put_bits(pb2, 1, s->interlaced_dct);

                put_bits(pb2, 1, 1);

                if (interleaved_stats)

                    s->misc_bits += get_bits_diff(s);

                /* motion vectors: 16x8 interlaced mode */

                ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);

                pred_y /= 2;

                put_bits(&s->pb, 1, s->field_select[0][0]);

                put_bits(&s->pb, 1, s->field_select[0][1]);

                ff_h263_encode_motion_vector(s,

                                             s->mv[0][0][0] - pred_x,

                                             s->mv[0][0][1] - pred_y,

                                             s->f_code);

                ff_h263_encode_motion_vector(s,

                                             s->mv[0][1][0] - pred_x,

                                             s->mv[0][1][1] - pred_y,

                                             s->f_code);

            } else {

                assert(s->mv_type == MV_TYPE_8X8);

                put_bits(&s->pb,

                         ff_h263_inter_MCBPC_bits[cbpc + 16],

                         ff_h263_inter_MCBPC_code[cbpc + 16]);

                put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]);

                if (!s->progressive_sequence && cbp)

                    put_bits(pb2, 1, s->interlaced_dct);

                if (interleaved_stats)

                    s->misc_bits += get_bits_diff(s);

                for (i = 0; i < 4; i++) {

                    /* motion vectors: 8x8 mode*/

                    ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y);

                    ff_h263_encode_motion_vector(s,

                                                 s->current_picture.motion_val[0][s->block_index[i]][0] - pred_x,

                                                 s->current_picture.motion_val[0][s->block_index[i]][1] - pred_y,

                                                 s->f_code);

                }

            }

            if (interleaved_stats)

                s->mv_bits += get_bits_diff(s);

            mpeg4_encode_blocks(s, block, NULL, NULL, NULL, tex_pb);

            if (interleaved_stats)

                s->p_tex_bits += get_bits_diff(s);

            s->f_count++;

        }

    } else {

        int cbp;

        int dc_diff[6];  // dc values with the dc prediction subtracted

        int dir[6];      // prediction direction

        int zigzag_last_index[6];

        uint8_t *scan_table[6];

        int i;

        for (i = 0; i < 6; i++)

            dc_diff[i] = ff_mpeg4_pred_dc(s, i, block[i][0], &dir[i], 1);

        if (s->flags & CODEC_FLAG_AC_PRED) {

            s->ac_pred = decide_ac_pred(s, block, dir, scan_table, zigzag_last_index);

        } else {

            for (i = 0; i < 6; i++)

                scan_table[i] = s->intra_scantable.permutated;

        }

        /* compute cbp */

        cbp = 0;

        for (i = 0; i < 6; i++)

            if (s->block_last_index[i] >= 1)

                cbp |= 1 << (5 - i);

        cbpc = cbp & 3;

        if (s->pict_type == AV_PICTURE_TYPE_I) {

            if (s->dquant)

                cbpc += 4;

            put_bits(&s->pb,

                     ff_h263_intra_MCBPC_bits[cbpc],

                     ff_h263_intra_MCBPC_code[cbpc]);

        } else {

            if (s->dquant)

                cbpc += 8;

            put_bits(&s->pb, 1, 0);     /* mb coded */

            put_bits(&s->pb,

                     ff_h263_inter_MCBPC_bits[cbpc + 4],

                     ff_h263_inter_MCBPC_code[cbpc + 4]);

        }

        put_bits(pb2, 1, s->ac_pred);

        cbpy = cbp >> 2;

        put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]);

        if (s->dquant)

            put_bits(dc_pb, 2, dquant_code[s->dquant + 2]);

        if (!s->progressive_sequence)

            put_bits(dc_pb, 1, s->interlaced_dct);

        if (interleaved_stats)

            s->misc_bits += get_bits_diff(s);

        mpeg4_encode_blocks(s, block, dc_diff, scan_table, dc_pb, tex_pb);

        if (interleaved_stats)

            s->i_tex_bits += get_bits_diff(s);

        s->i_count++;

        /* restore ac coeffs & last_index stuff

         * if we messed them up with the prediction */

        if (s->ac_pred)

            restore_ac_coeffs(s, block, dir, scan_table, zigzag_last_index);

    }

}


static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1,

                               const uint8_t *buf, int buf_size, int is_start)

{

    MpegTSSectionFilter *tss = &tss1->u.section_filter;

    int len;

    if (is_start) {

        memcpy(tss->section_buf, buf, buf_size);

        tss->section_index = buf_size;

        tss->section_h_size = -1;

        tss->end_of_section_reached = 0;

    } else {

        if (tss->end_of_section_reached)

            return;

        len = 4096 - tss->section_index;

        if (buf_size < len)

            len = buf_size;

        memcpy(tss->section_buf + tss->section_index, buf, len);

        tss->section_index += len;

    }

    /* compute section length if possible */

    if (tss->section_h_size == -1 && tss->section_index >= 3) {

        len = (AV_RB16(tss->section_buf + 1) & 0xfff) + 3;

        if (len > 4096)

            return;

        tss->section_h_size = len;

    }

    if (tss->section_h_size != -1 &&

        tss->section_index >= tss->section_h_size) {

        int crc_valid = 1;

        tss->end_of_section_reached = 1;

        if (tss->check_crc) {

            crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, tss->section_buf, tss->section_h_size);

            if (crc_valid) {

                ts->crc_validity[ tss1->pid ] = 100;

            }else if (ts->crc_validity[ tss1->pid ] > -10) {

                ts->crc_validity[ tss1->pid ]--;

            }else

                crc_valid = 2;

        }

        if (crc_valid)

            tss->section_cb(tss1, tss->section_buf, tss->section_h_size);

    }

}