static int ea_read_packet(AVFormatContext *s,
                          AVPacket *pkt)
{
    EaDemuxContext *ea = s->priv_data;
    ByteIOContext *pb = s->pb;
    int ret = 0;
    int packet_read = 0;
    unsigned int chunk_type, chunk_size;
    int key = 0;
    int av_uninit(num_samples);

    while (!packet_read) {
        chunk_type = get_le32(pb);
        chunk_size = (ea->big_endian ? get_be32(pb) : get_le32(pb)) - 8;

        switch (chunk_type) {
        /* audio data */
        case ISNh_TAG:
            /* header chunk also contains data; skip over the header portion*/
            url_fskip(pb, 32);
            chunk_size -= 32;
        case ISNd_TAG:
        case SCDl_TAG:
        case SNDC_TAG:
        case SDEN_TAG:
            if (!ea->audio_codec) {
                url_fskip(pb, chunk_size);
                break;
            } else if (ea->audio_codec == CODEC_ID_PCM_S16LE_PLANAR ||
                       ea->audio_codec == CODEC_ID_MP3) {
                num_samples = get_le32(pb);
                url_fskip(pb, 8);
                chunk_size -= 12;
            }
            ret = av_get_packet(pb, pkt, chunk_size);
            if (ret != chunk_size)
                ret = AVERROR(EIO);
            else {
                    pkt->stream_index = ea->audio_stream_index;
                    pkt->pts = 90000;
                    pkt->pts *= ea->audio_frame_counter;
                    pkt->pts /= ea->sample_rate;

                    switch (ea->audio_codec) {
                    case CODEC_ID_ADPCM_EA:
                    /* 2 samples/byte, 1 or 2 samples per frame depending
                     * on stereo; chunk also has 12-byte header */
                    ea->audio_frame_counter += ((chunk_size - 12) * 2) /
                        ea->num_channels;
                        break;
                    case CODEC_ID_PCM_S16LE_PLANAR:
                    case CODEC_ID_MP3:
                        ea->audio_frame_counter += num_samples;
                        break;
                    default:
                        ea->audio_frame_counter += chunk_size /
                            (ea->bytes * ea->num_channels);
                    }
            }

            packet_read = 1;
            break;

        /* ending tag */
        case 0:
        case ISNe_TAG:
        case SCEl_TAG:
        case SEND_TAG:
        case SEEN_TAG:
            ret = AVERROR(EIO);
            packet_read = 1;
            break;

        case MVIh_TAG:
        case kVGT_TAG:
        case pQGT_TAG:
        case TGQs_TAG:
            key = PKT_FLAG_KEY;
        case MVIf_TAG:
        case fVGT_TAG:
            url_fseek(pb, -8, SEEK_CUR);     // include chunk preamble
            chunk_size += 8;
            goto get_video_packet;

        case mTCD_TAG:
            url_fseek(pb, 8, SEEK_CUR);  // skip ea dct header
            chunk_size -= 8;
            goto get_video_packet;

        case MV0K_TAG:
        case MPCh_TAG:
        case pIQT_TAG:
            key = PKT_FLAG_KEY;
        case MV0F_TAG:
get_video_packet:
            ret = av_get_packet(pb, pkt, chunk_size);
            if (ret != chunk_size)
                ret = AVERROR_IO;
            else {
                pkt->stream_index = ea->video_stream_index;
                pkt->flags |= key;
            }
            packet_read = 1;
            break;

        default:
            url_fseek(pb, chunk_size, SEEK_CUR);
            break;
        }
    }

    return ret;
}