static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2,
                            const DVprofile *sys)
{
    int size, chan, i, j, d, of, smpls, freq, quant, half_ch;
    uint16_t lc, rc;
    const uint8_t* as_pack;
    as_pack = dv_extract_pack(frame, dv_audio_source);
    if (!as_pack)
        return 0;
    smpls = as_pack[1] & 0x3f;
    freq = (as_pack[4] >> 3) & 0x07;
    quant = as_pack[4] & 0x07;
    if (quant > 1)
        return -1;
    size = (sys->audio_min_samples[freq] + smpls) * 4;
    half_ch = sys->difseg_size/2;
    for (chan = 0; chan < sys->n_difchan; chan++) {
        for (i = 0; i < sys->difseg_size; i++) {
            frame += 6 * 80;
            if (quant == 1 && i == half_ch) {
                if (!pcm2)
                    break;
                else
                    pcm = pcm2;
            }
            for (j = 0; j < 9; j++) {
                for (d = 8; d < 80; d += 2) {
                    if (quant == 0) {
                        of = sys->audio_shuffle[i][j] + (d - 8)/2 * sys->audio_stride;
                        if (of*2 >= size)
                            continue;
                        pcm[of*2] = frame[d+1];
                        pcm[of*2+1] = frame[d];
                        if (pcm[of*2+1] == 0x80 && pcm[of*2] == 0x00)
                            pcm[of*2+1] = 0;
                    } else {
                        lc = ((uint16_t)frame[d] << 4) |
                             ((uint16_t)frame[d+2] >> 4);
                        rc = ((uint16_t)frame[d+1] << 4) |
                             ((uint16_t)frame[d+2] & 0x0f);
                        lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));
                        rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));
                        of = sys->audio_shuffle[i%half_ch][j] + (d - 8)/3 * sys->audio_stride;
                        if (of*2 >= size)
                            continue;
                        pcm[of*2] = lc & 0xff;
                        pcm[of*2+1] = lc >> 8;
                        of = sys->audio_shuffle[i%half_ch+half_ch][j] +
                            (d - 8)/3 * sys->audio_stride;
                        pcm[of*2] = rc & 0xff;
                        pcm[of*2+1] = rc >> 8;
                        ++d;
                    }
                }
                frame += 16 * 80;
            }
        }
        if(!pcm2)
            break;
        pcm = pcm2;
    }
    return size;
}
['static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)\n{\n    AVIContext *avi = s->priv_data;\n    ByteIOContext *pb = s->pb;\n    int n, d[8], size;\n    offset_t i, sync;\n    void* dstr;\n    if (ENABLE_DV_DEMUXER && avi->dv_demux) {\n        size = dv_get_packet(avi->dv_demux, pkt);\n        if (size >= 0)\n            return size;\n    }\n    if(avi->non_interleaved){\n        int best_stream_index = 0;\n        AVStream *best_st= NULL;\n        AVIStream *best_ast;\n        int64_t best_ts= INT64_MAX;\n        int i;\n        for(i=0; i<s->nb_streams; i++){\n            AVStream *st = s->streams[i];\n            AVIStream *ast = st->priv_data;\n            int64_t ts= ast->frame_offset;\n            if(ast->sample_size)\n                ts /= ast->sample_size;\n            ts= av_rescale(ts, AV_TIME_BASE * (int64_t)st->time_base.num, st->time_base.den);\n            if(ts < best_ts){\n                best_ts= ts;\n                best_st= st;\n                best_stream_index= i;\n            }\n        }\n        best_ast = best_st->priv_data;\n        best_ts= av_rescale(best_ts, best_st->time_base.den, AV_TIME_BASE * (int64_t)best_st->time_base.num);\n        if(best_ast->remaining)\n            i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);\n        else\n            i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);\n        if(i>=0){\n            int64_t pos= best_st->index_entries[i].pos;\n            pos += best_ast->packet_size - best_ast->remaining;\n            url_fseek(s->pb, pos + 8, SEEK_SET);\n            assert(best_ast->remaining <= best_ast->packet_size);\n            avi->stream_index= best_stream_index;\n            if(!best_ast->remaining)\n                best_ast->packet_size=\n                best_ast->remaining= best_st->index_entries[i].size;\n        }\n    }\nresync:\n    if(avi->stream_index >= 0){\n        AVStream *st= s->streams[ avi->stream_index ];\n        AVIStream *ast= st->priv_data;\n        int size;\n        if(ast->sample_size <= 1)\n            size= INT_MAX;\n        else if(ast->sample_size < 32)\n            size= 64*ast->sample_size;\n        else\n            size= ast->sample_size;\n        if(size > ast->remaining)\n            size= ast->remaining;\n        av_get_packet(pb, pkt, size);\n        if(ast->has_pal && pkt->data && pkt->size<(unsigned)INT_MAX/2){\n            ast->has_pal=0;\n            pkt->size += 4*256;\n            pkt->data = av_realloc(pkt->data, pkt->size + FF_INPUT_BUFFER_PADDING_SIZE);\n            if(pkt->data)\n                memcpy(pkt->data + pkt->size - 4*256, ast->pal, 4*256);\n        }\n        if (ENABLE_DV_DEMUXER && avi->dv_demux) {\n            dstr = pkt->destruct;\n            size = dv_produce_packet(avi->dv_demux, pkt,\n                                    pkt->data, pkt->size);\n            pkt->destruct = dstr;\n            pkt->flags |= PKT_FLAG_KEY;\n        } else {\n            pkt->dts = ast->frame_offset;\n            if(ast->sample_size)\n                pkt->dts /= ast->sample_size;\n            pkt->stream_index = avi->stream_index;\n            if (st->codec->codec_type == CODEC_TYPE_VIDEO) {\n                AVIndexEntry *e;\n                int index;\n                assert(st->index_entries);\n                index= av_index_search_timestamp(st, pkt->dts, 0);\n                e= &st->index_entries[index];\n                if(index >= 0 && e->timestamp == ast->frame_offset){\n                    if (e->flags & AVINDEX_KEYFRAME)\n                        pkt->flags |= PKT_FLAG_KEY;\n                }\n            } else {\n                pkt->flags |= PKT_FLAG_KEY;\n            }\n            if(ast->sample_size)\n                ast->frame_offset += pkt->size;\n            else\n                ast->frame_offset++;\n        }\n        ast->remaining -= size;\n        if(!ast->remaining){\n            avi->stream_index= -1;\n            ast->packet_size= 0;\n        }\n        return size;\n    }\n    memset(d, -1, sizeof(int)*8);\n    for(i=sync=url_ftell(pb); !url_feof(pb); i++) {\n        int j;\n        for(j=0; j<7; j++)\n            d[j]= d[j+1];\n        d[7]= get_byte(pb);\n        size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24);\n        if(    d[2] >= \'0\' && d[2] <= \'9\'\n            && d[3] >= \'0\' && d[3] <= \'9\'){\n            n= (d[2] - \'0\') * 10 + (d[3] - \'0\');\n        }else{\n            n= 100;\n        }\n        if(i + size > avi->fsize || d[0]<0)\n            continue;\n        if(  (d[0] == \'i\' && d[1] == \'x\' && n < s->nb_streams)\n           ||(d[0] == \'J\' && d[1] == \'U\' && d[2] == \'N\' && d[3] == \'K\')\n           ||(d[0] == \'i\' && d[1] == \'d\' && d[2] == \'x\' && d[3] == \'1\')){\n            url_fskip(pb, size);\n            goto resync;\n        }\n        if(    d[0] >= \'0\' && d[0] <= \'9\'\n            && d[1] >= \'0\' && d[1] <= \'9\'){\n            n= (d[0] - \'0\') * 10 + (d[1] - \'0\');\n        }else{\n            n= 100;\n        }\n        if(n < s->nb_streams){\n            AVStream *st;\n            AVIStream *ast;\n            st = s->streams[n];\n            ast = st->priv_data;\n            if(s->nb_streams>=2){\n                AVStream *st1  = s->streams[1];\n                AVIStream *ast1= st1->priv_data;\n                if(   d[2] == \'w\' && d[3] == \'b\'\n                   && n==0\n                   && st ->codec->codec_type == CODEC_TYPE_VIDEO\n                   && st1->codec->codec_type == CODEC_TYPE_AUDIO\n                   && ast->prefix == \'d\'*256+\'c\'\n                   && (d[2]*256+d[3] == ast1->prefix || !ast1->prefix_count)\n                  ){\n                    n=1;\n                    st = st1;\n                    ast = ast1;\n                    av_log(s, AV_LOG_WARNING, "Invalid stream+prefix combination, assuming audio\\n");\n                }\n            }\n            if(   (st->discard >= AVDISCARD_DEFAULT && size==0)\n               || st->discard >= AVDISCARD_ALL){\n                if(ast->sample_size) ast->frame_offset += pkt->size;\n                else                 ast->frame_offset++;\n                url_fskip(pb, size);\n                goto resync;\n            }\n            if (d[2] == \'p\' && d[3] == \'c\' && size<=4*256+4) {\n                int k = get_byte(pb);\n                int last = (k + get_byte(pb) - 1) & 0xFF;\n                get_le16(pb);\n                for (; k <= last; k++)\n                    ast->pal[k] = get_be32(pb)>>8;\n                ast->has_pal= 1;\n                goto resync;\n            } else if(   ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) ||\n                         d[2]*256+d[3] == ast->prefix  ) {\n                if(d[2]*256+d[3] == ast->prefix)\n                    ast->prefix_count++;\n                else{\n                    ast->prefix= d[2]*256+d[3];\n                    ast->prefix_count= 0;\n                }\n                avi->stream_index= n;\n                ast->packet_size= size + 8;\n                ast->remaining= size;\n                {\n                    uint64_t pos= url_ftell(pb) - 8;\n                    if(!st->index_entries || !st->nb_index_entries || st->index_entries[st->nb_index_entries - 1].pos < pos){\n                        av_add_index_entry(st, pos, ast->frame_offset / FFMAX(1, ast->sample_size), size, 0, AVINDEX_KEYFRAME);\n                    }\n                }\n                goto resync;\n            }\n        }\n    }\n    return -1;\n}', 'int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,\n                      uint8_t* buf, int buf_size)\n{\n    int size, i;\n    if (buf_size < DV_PROFILE_BYTES ||\n        !(c->sys = dv_frame_profile(buf)) ||\n        buf_size < c->sys->frame_size) {\n          return -1;\n    }\n    size = dv_extract_audio_info(c, buf);\n    for (i=0; i<c->ach; i++) {\n       c->audio_pkt[i].size = size;\n       c->audio_pkt[i].pts  = c->abytes * 30000*8 / c->ast[i]->codec->bit_rate;\n    }\n    dv_extract_audio(buf, c->audio_buf[0], c->audio_buf[1], c->sys);\n    c->abytes += size;\n    size = dv_extract_video_info(c, buf);\n    av_init_packet(pkt);\n    pkt->data     = buf;\n    pkt->size     = size;\n    pkt->flags   |= PKT_FLAG_KEY;\n    pkt->stream_index = c->vst->id;\n    pkt->pts      = c->frames;\n    c->frames++;\n    return size;\n}', 'static inline const DVprofile* dv_frame_profile(const uint8_t* frame)\n{\n    if ((frame[3] & 0x80) == 0) {\n        if ((frame[80*5 + 48 + 3] & 0x4) && (frame[80*5 + 48] == dv_video_source)) {\n            return &dv_profiles[3];\n        } else {\n            return &dv_profiles[0];\n        }\n    } else {\n        if ((frame[80*5 + 48 + 3] & 0x4) && (frame[80*5 + 48] == dv_video_source)) {\n            return &dv_profiles[4];\n        } else if ((frame[5] & 0x07) == 0) {\n            return &dv_profiles[1];\n        } else\n            return &dv_profiles[2];\n    }\n}', 'static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame)\n{\n    const uint8_t* as_pack;\n    int freq, stype, smpls, quant, i, ach;\n    as_pack = dv_extract_pack(frame, dv_audio_source);\n    if (!as_pack || !c->sys) {\n        c->ach = 0;\n        return 0;\n    }\n    smpls = as_pack[1] & 0x3f;\n    freq = (as_pack[4] >> 3) & 0x07;\n    stype = (as_pack[3] & 0x1f);\n    quant = as_pack[4] & 0x07;\n    ach = (stype == 2 || (quant && (freq == 2))) ? 2 : 1;\n    for (i=0; i<ach; i++) {\n       if (!c->ast[i]) {\n           c->ast[i] = av_new_stream(c->fctx, 0);\n           if (!c->ast[i])\n               break;\n           av_set_pts_info(c->ast[i], 64, 1, 30000);\n           c->ast[i]->codec->codec_type = CODEC_TYPE_AUDIO;\n           c->ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE;\n           av_init_packet(&c->audio_pkt[i]);\n           c->audio_pkt[i].size     = 0;\n           c->audio_pkt[i].data     = c->audio_buf[i];\n           c->audio_pkt[i].stream_index = c->ast[i]->index;\n           c->audio_pkt[i].flags |= PKT_FLAG_KEY;\n       }\n       c->ast[i]->codec->sample_rate = dv_audio_frequency[freq];\n       c->ast[i]->codec->channels = 2;\n       c->ast[i]->codec->bit_rate = 2 * dv_audio_frequency[freq] * 16;\n       c->ast[i]->start_time = 0;\n    }\n    c->ach = i;\n    return (c->sys->audio_min_samples[freq] + smpls) * 4;  ;\n}', 'static const uint8_t* dv_extract_pack(uint8_t* frame, enum dv_pack_type t)\n{\n    int offs;\n    switch (t) {\n    case dv_audio_source:\n          offs = (80*6 + 80*16*3 + 3);\n          break;\n    case dv_audio_control:\n          offs = (80*6 + 80*16*4 + 3);\n          break;\n    case dv_video_control:\n          offs = (80*5 + 48 + 5);\n          break;\n    default:\n          return NULL;\n    }\n    return (frame[offs] == t ? &frame[offs] : NULL);\n}', 'static int dv_extract_audio(uint8_t* frame, uint8_t* pcm, uint8_t* pcm2,\n                            const DVprofile *sys)\n{\n    int size, chan, i, j, d, of, smpls, freq, quant, half_ch;\n    uint16_t lc, rc;\n    const uint8_t* as_pack;\n    as_pack = dv_extract_pack(frame, dv_audio_source);\n    if (!as_pack)\n        return 0;\n    smpls = as_pack[1] & 0x3f;\n    freq = (as_pack[4] >> 3) & 0x07;\n    quant = as_pack[4] & 0x07;\n    if (quant > 1)\n        return -1;\n    size = (sys->audio_min_samples[freq] + smpls) * 4;\n    half_ch = sys->difseg_size/2;\n    for (chan = 0; chan < sys->n_difchan; chan++) {\n        for (i = 0; i < sys->difseg_size; i++) {\n            frame += 6 * 80;\n            if (quant == 1 && i == half_ch) {\n                if (!pcm2)\n                    break;\n                else\n                    pcm = pcm2;\n            }\n            for (j = 0; j < 9; j++) {\n                for (d = 8; d < 80; d += 2) {\n                    if (quant == 0) {\n                        of = sys->audio_shuffle[i][j] + (d - 8)/2 * sys->audio_stride;\n                        if (of*2 >= size)\n                            continue;\n                        pcm[of*2] = frame[d+1];\n                        pcm[of*2+1] = frame[d];\n                        if (pcm[of*2+1] == 0x80 && pcm[of*2] == 0x00)\n                            pcm[of*2+1] = 0;\n                    } else {\n                        lc = ((uint16_t)frame[d] << 4) |\n                             ((uint16_t)frame[d+2] >> 4);\n                        rc = ((uint16_t)frame[d+1] << 4) |\n                             ((uint16_t)frame[d+2] & 0x0f);\n                        lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc));\n                        rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc));\n                        of = sys->audio_shuffle[i%half_ch][j] + (d - 8)/3 * sys->audio_stride;\n                        if (of*2 >= size)\n                            continue;\n                        pcm[of*2] = lc & 0xff;\n                        pcm[of*2+1] = lc >> 8;\n                        of = sys->audio_shuffle[i%half_ch+half_ch][j] +\n                            (d - 8)/3 * sys->audio_stride;\n                        pcm[of*2] = rc & 0xff;\n                        pcm[of*2+1] = rc >> 8;\n                        ++d;\n                    }\n                }\n                frame += 16 * 80;\n            }\n        }\n        if(!pcm2)\n            break;\n        pcm = pcm2;\n    }\n    return size;\n}']