int ff_v4l2_context_init(V4L2Context* ctx) { V4L2m2mContext *s = ctx_to_m2mctx(ctx); struct v4l2_requestbuffers req; int ret, i; if (!v4l2_type_supported(ctx)) { av_log(logger(ctx), AV_LOG_ERROR, "type %i not supported\n", ctx->type); return AVERROR_PATCHWELCOME; } ret = ioctl(s->fd, VIDIOC_G_FMT, &ctx->format); if (ret) av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT failed\n", ctx->name); memset(&req, 0, sizeof(req)); req.count = ctx->num_buffers; req.memory = V4L2_MEMORY_MMAP; req.type = ctx->type; ret = ioctl(s->fd, VIDIOC_REQBUFS, &req); if (ret < 0) return AVERROR(errno); ctx->num_buffers = req.count; ctx->buffers = av_mallocz(ctx->num_buffers * sizeof(V4L2Buffer)); if (!ctx->buffers) { av_log(logger(ctx), AV_LOG_ERROR, "%s malloc enomem\n", ctx->name); return AVERROR(ENOMEM); } for (i = 0; i < req.count; i++) { ctx->buffers[i].context = ctx; ret = ff_v4l2_buffer_initialize(&ctx->buffers[i], i); if (ret < 0) { av_log(logger(ctx), AV_LOG_ERROR, "%s buffer initialization (%s)\n", ctx->name, av_err2str(ret)); av_free(ctx->buffers); return ret; } } av_log(logger(ctx), AV_LOG_DEBUG, "%s: %s %02d buffers initialized: %04ux%04u, sizeimage %08u, bytesperline %08u\n", ctx->name, V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? av_fourcc2str(ctx->format.fmt.pix_mp.pixelformat) : av_fourcc2str(ctx->format.fmt.pix.pixelformat), req.count, v4l2_get_width(&ctx->format), v4l2_get_height(&ctx->format), V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].sizeimage : ctx->format.fmt.pix.sizeimage, V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline : ctx->format.fmt.pix.bytesperline); return 0; }
static int wc3_read_header(AVFormatContext *s) { Wc3DemuxContext *wc3 = s->priv_data; AVIOContext *pb = s->pb; unsigned int fourcc_tag; unsigned int size; AVStream *st; int ret = 0; char *buffer; /* default context members */ wc3->width = WC3_DEFAULT_WIDTH; wc3->height = WC3_DEFAULT_HEIGHT; wc3->pts = 0; wc3->video_stream_index = wc3->audio_stream_index = 0; av_init_packet(&wc3->vpkt); wc3->vpkt.data = NULL; wc3->vpkt.size = 0; /* skip the first 3 32-bit numbers */ avio_skip(pb, 12); /* traverse through the chunks and load the header information before * the first BRCH tag */ fourcc_tag = avio_rl32(pb); size = (avio_rb32(pb) + 1) & (~1); do { switch (fourcc_tag) { case SOND_TAG: case INDX_TAG: /* SOND unknown, INDX unnecessary; ignore both */ avio_skip(pb, size); break; case PC__TAG: /* number of palettes, unneeded */ avio_skip(pb, 12); break; case BNAM_TAG: /* load up the name */ buffer = av_malloc(size+1); if (!buffer) return AVERROR(ENOMEM); if ((ret = avio_read(pb, buffer, size)) != size) return AVERROR(EIO); buffer[size] = 0; av_dict_set(&s->metadata, "title", buffer, AV_DICT_DONT_STRDUP_VAL); break; case SIZE_TAG: /* video resolution override */ wc3->width = avio_rl32(pb); wc3->height = avio_rl32(pb); break; case PALT_TAG: /* one of several palettes */ avio_seek(pb, -8, SEEK_CUR); av_append_packet(pb, &wc3->vpkt, 8 + PALETTE_SIZE); break; default: av_log(s, AV_LOG_ERROR, "unrecognized WC3 chunk: %s\n", av_fourcc2str(fourcc_tag)); return AVERROR_INVALIDDATA; } fourcc_tag = avio_rl32(pb); /* chunk sizes are 16-bit aligned */ size = (avio_rb32(pb) + 1) & (~1); if (avio_feof(pb)) return AVERROR(EIO); } while (fourcc_tag != BRCH_TAG); /* initialize the decoder streams */ st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 33, 1, WC3_FRAME_FPS); wc3->video_stream_index = st->index; st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; st->codecpar->codec_id = AV_CODEC_ID_XAN_WC3; st->codecpar->codec_tag = 0; /* no fourcc */ st->codecpar->width = wc3->width; st->codecpar->height = wc3->height; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 33, 1, WC3_FRAME_FPS); wc3->audio_stream_index = st->index; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; st->codecpar->codec_tag = 1; st->codecpar->channels = WC3_AUDIO_CHANNELS; st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; st->codecpar->bits_per_coded_sample = WC3_AUDIO_BITS; st->codecpar->sample_rate = WC3_SAMPLE_RATE; st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; st->codecpar->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS; return 0; }
static int xwma_read_header(AVFormatContext *s) { int64_t size; int ret = 0; uint32_t dpds_table_size = 0; uint32_t *dpds_table = NULL; unsigned int tag; AVIOContext *pb = s->pb; AVStream *st; XWMAContext *xwma = s->priv_data; int i; /* The following code is mostly copied from wav.c, with some * minor alterations. */ /* check RIFF header */ tag = avio_rl32(pb); if (tag != MKTAG('R', 'I', 'F', 'F')) return -1; avio_rl32(pb); /* file size */ tag = avio_rl32(pb); if (tag != MKTAG('X', 'W', 'M', 'A')) return -1; /* parse fmt header */ tag = avio_rl32(pb); if (tag != MKTAG('f', 'm', 't', ' ')) return -1; size = avio_rl32(pb); st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); ret = ff_get_wav_header(s, pb, st->codecpar, size, 0); if (ret < 0) return ret; st->need_parsing = AVSTREAM_PARSE_NONE; /* XWMA encoder only allows a few channel/sample rate/bitrate combinations, * but some create identical files with fake bitrate (1ch 22050hz at * 20/48/192kbps are all 20kbps, with the exact same codec data). * Decoder needs correct bitrate to work, so it's normalized here. */ if (st->codecpar->codec_id == AV_CODEC_ID_WMAV2) { int ch = st->codecpar->channels; int sr = st->codecpar->sample_rate; int br = st->codecpar->bit_rate; if (ch == 1) { if (sr == 22050 && (br==48000 || br==192000)) br = 20000; else if (sr == 32000 && (br==48000 || br==192000)) br = 20000; else if (sr == 44100 && (br==96000 || br==192000)) br = 48000; } else if (ch == 2) { if (sr == 22050 && (br==48000 || br==192000)) br = 32000; else if (sr == 32000 && (br==192000)) br = 48000; } st->codecpar->bit_rate = br; } /* Normally xWMA can only contain WMAv2 with 1/2 channels, * and WMAPRO with 6 channels. */ if (st->codecpar->codec_id != AV_CODEC_ID_WMAV2 && st->codecpar->codec_id != AV_CODEC_ID_WMAPRO) { avpriv_request_sample(s, "Unexpected codec (tag %s; id %d)", av_fourcc2str(st->codecpar->codec_tag), st->codecpar->codec_id); } else { /* xWMA shouldn't have extradata. But the WMA codecs require it, * so we provide our own fake extradata. * * First, check that there really was no extradata in the header. If * there was, then try to use it, after asking the user to provide a * sample of this unusual file. */ if (st->codecpar->extradata_size != 0) { /* Surprise, surprise: We *did* get some extradata. No idea * if it will work, but just go on and try it, after asking * the user for a sample. */ avpriv_request_sample(s, "Unexpected extradata (%d bytes)", st->codecpar->extradata_size); } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) { if (ff_alloc_extradata(st->codecpar, 18)) return AVERROR(ENOMEM); memset(st->codecpar->extradata, 0, st->codecpar->extradata_size); st->codecpar->extradata[ 0] = st->codecpar->bits_per_coded_sample; st->codecpar->extradata[14] = 224; } else { if (ff_alloc_extradata(st->codecpar, 6)) return AVERROR(ENOMEM); memset(st->codecpar->extradata, 0, st->codecpar->extradata_size); /* setup extradata with our experimentally obtained value */ st->codecpar->extradata[4] = 31; } } if (!st->codecpar->channels) { av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n", st->codecpar->channels); return AVERROR_INVALIDDATA; } if (!st->codecpar->bits_per_coded_sample) { av_log(s, AV_LOG_WARNING, "Invalid bits_per_coded_sample: %d\n", st->codecpar->bits_per_coded_sample); return AVERROR_INVALIDDATA; } /* set the sample rate */ avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); /* parse the remaining RIFF chunks */ for (;;) { if (pb->eof_reached) { ret = AVERROR_EOF; goto fail; } /* read next chunk tag */ tag = avio_rl32(pb); size = avio_rl32(pb); if (tag == MKTAG('d', 'a', 't', 'a')) { /* We assume that the data chunk comes last. */ break; } else if (tag == MKTAG('d','p','d','s')) { /* Quoting the MSDN xWMA docs on the dpds chunk: "Contains the * decoded packet cumulative data size array, each element is the * number of bytes accumulated after the corresponding xWMA packet * is decoded in order." * * Each packet has size equal to st->codecpar->block_align, which in * all cases I saw so far was always 2230. Thus, we can use the * dpds data to compute a seeking index. */ /* Error out if there is more than one dpds chunk. */ if (dpds_table) { av_log(s, AV_LOG_ERROR, "two dpds chunks present\n"); ret = AVERROR_INVALIDDATA; goto fail; } /* Compute the number of entries in the dpds chunk. */ if (size & 3) { /* Size should be divisible by four */ av_log(s, AV_LOG_WARNING, "dpds chunk size %"PRId64" not divisible by 4\n", size); } dpds_table_size = size / 4; if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) { av_log(s, AV_LOG_ERROR, "dpds chunk size %"PRId64" invalid\n", size); return AVERROR_INVALIDDATA; } /* Allocate some temporary storage to keep the dpds data around. * for processing later on. */ dpds_table = av_malloc_array(dpds_table_size, sizeof(uint32_t)); if (!dpds_table) { return AVERROR(ENOMEM); } for (i = 0; i < dpds_table_size; ++i) { dpds_table[i] = avio_rl32(pb); size -= 4; } } avio_skip(pb, size); } /* Determine overall data length */ if (size < 0) { ret = AVERROR_INVALIDDATA; goto fail; } if (!size) { xwma->data_end = INT64_MAX; } else xwma->data_end = avio_tell(pb) + size; if (dpds_table && dpds_table_size) { int64_t cur_pos; const uint32_t bytes_per_sample = (st->codecpar->channels * st->codecpar->bits_per_coded_sample) >> 3; /* Estimate the duration from the total number of output bytes. */ const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1]; if (!bytes_per_sample) { av_log(s, AV_LOG_ERROR, "Invalid bits_per_coded_sample %d for %d channels\n", st->codecpar->bits_per_coded_sample, st->codecpar->channels); ret = AVERROR_INVALIDDATA; goto fail; } st->duration = total_decoded_bytes / bytes_per_sample; /* Use the dpds data to build a seek table. We can only do this after * we know the offset to the data chunk, as we need that to determine * the actual offset to each input block. * Note: If we allowed ourselves to assume that the data chunk always * follows immediately after the dpds block, we could of course guess * the data block's start offset already while reading the dpds chunk. * I decided against that, just in case other chunks ever are * discovered. */ cur_pos = avio_tell(pb); for (i = 0; i < dpds_table_size; ++i) { /* From the number of output bytes that would accumulate in the * output buffer after decoding the first (i+1) packets, we compute * an offset / timestamp pair. */ av_add_index_entry(st, cur_pos + (i+1) * st->codecpar->block_align, /* pos */ dpds_table[i] / bytes_per_sample, /* timestamp */ st->codecpar->block_align, /* size */ 0, /* duration */ AVINDEX_KEYFRAME); } } else if (st->codecpar->bit_rate) {
static int wc3_read_packet(AVFormatContext *s, AVPacket *pkt) { Wc3DemuxContext *wc3 = s->priv_data; AVIOContext *pb = s->pb; unsigned int fourcc_tag; unsigned int size; int packet_read = 0; int ret = 0; unsigned char text[1024]; while (!packet_read) { fourcc_tag = avio_rl32(pb); /* chunk sizes are 16-bit aligned */ size = (avio_rb32(pb) + 1) & (~1); if (avio_feof(pb)) return AVERROR(EIO); switch (fourcc_tag) { case BRCH_TAG: /* no-op */ break; case SHOT_TAG: /* load up new palette */ avio_seek(pb, -8, SEEK_CUR); av_append_packet(pb, &wc3->vpkt, 8 + 4); break; case VGA__TAG: /* send out video chunk */ avio_seek(pb, -8, SEEK_CUR); ret= av_append_packet(pb, &wc3->vpkt, 8 + size); // ignore error if we have some data if (wc3->vpkt.size > 0) ret = 0; *pkt = wc3->vpkt; wc3->vpkt.data = NULL; wc3->vpkt.size = 0; pkt->stream_index = wc3->video_stream_index; pkt->pts = wc3->pts; packet_read = 1; break; case TEXT_TAG: /* subtitle chunk */ if ((unsigned)size > sizeof(text) || (ret = avio_read(pb, text, size)) != size) ret = AVERROR(EIO); else { int i = 0; av_log (s, AV_LOG_DEBUG, "Subtitle time!\n"); if (i >= size || av_strnlen(&text[i + 1], size - i - 1) >= size - i - 1) return AVERROR_INVALIDDATA; av_log (s, AV_LOG_DEBUG, " inglish: %s\n", &text[i + 1]); i += text[i] + 1; if (i >= size || av_strnlen(&text[i + 1], size - i - 1) >= size - i - 1) return AVERROR_INVALIDDATA; av_log (s, AV_LOG_DEBUG, " doytsch: %s\n", &text[i + 1]); i += text[i] + 1; if (i >= size || av_strnlen(&text[i + 1], size - i - 1) >= size - i - 1) return AVERROR_INVALIDDATA; av_log (s, AV_LOG_DEBUG, " fronsay: %s\n", &text[i + 1]); } break; case AUDI_TAG: /* send out audio chunk */ ret= av_get_packet(pb, pkt, size); pkt->stream_index = wc3->audio_stream_index; pkt->pts = wc3->pts; /* time to advance pts */ wc3->pts++; packet_read = 1; break; default: av_log(s, AV_LOG_ERROR, "unrecognized WC3 chunk: %s\n", av_fourcc2str(fourcc_tag)); ret = AVERROR_INVALIDDATA; packet_read = 1; break; } } return ret; }
static int apng_read_packet(AVFormatContext *s, AVPacket *pkt) { APNGDemuxContext *ctx = s->priv_data; int64_t ret; int64_t size; AVIOContext *pb = s->pb; uint32_t len, tag; /* * fcTL chunk length, in bytes: * 4 (length) * 4 (tag) * 26 (actual chunk) * 4 (crc) bytes * and needed next: * 4 (length) * 4 (tag (must be fdAT or IDAT)) */ /* if num_play is not 1, then the seekback is already guaranteed */ if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 46)) < 0) return ret; len = avio_rb32(pb); tag = avio_rl32(pb); if (avio_feof(pb)) return AVERROR_EOF; switch (tag) { case MKTAG('f', 'c', 'T', 'L'): if (len != 26) return AVERROR_INVALIDDATA; if ((ret = decode_fctl_chunk(s, ctx, pkt)) < 0) return ret; /* fcTL must precede fdAT or IDAT */ len = avio_rb32(pb); tag = avio_rl32(pb); if (len > 0x7fffffff || tag != MKTAG('f', 'd', 'A', 'T') && tag != MKTAG('I', 'D', 'A', 'T')) return AVERROR_INVALIDDATA; size = 38 /* fcTL */ + 8 /* len, tag */ + len + 4 /* crc */; if (size > INT_MAX) return AVERROR(EINVAL); if ((ret = avio_seek(pb, -46, SEEK_CUR)) < 0 || (ret = av_append_packet(pb, pkt, size)) < 0) return ret; if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0) return ret; len = avio_rb32(pb); tag = avio_rl32(pb); while (tag && tag != MKTAG('f', 'c', 'T', 'L') && tag != MKTAG('I', 'E', 'N', 'D')) { if (len > 0x7fffffff) return AVERROR_INVALIDDATA; if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 || (ret = av_append_packet(pb, pkt, len + 12)) < 0) return ret; if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0) return ret; len = avio_rb32(pb); tag = avio_rl32(pb); } if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0) return ret; if (ctx->is_key_frame) pkt->flags |= AV_PKT_FLAG_KEY; pkt->pts = pkt->dts = AV_NOPTS_VALUE; pkt->duration = ctx->pkt_duration; return ret; case MKTAG('I', 'E', 'N', 'D'): ctx->cur_loop++; if (ctx->ignore_loop || ctx->num_play >= 1 && ctx->cur_loop == ctx->num_play) { avio_seek(pb, -8, SEEK_CUR); return AVERROR_EOF; } if ((ret = avio_seek(pb, s->streams[0]->codecpar->extradata_size + 8, SEEK_SET)) < 0) return ret; return 0; default: avpriv_request_sample(s, "In-stream tag=%s (0x%08"PRIX32") len=%"PRIu32, av_fourcc2str(tag), tag, len); avio_skip(pb, len + 4); } /* Handle the unsupported yet cases */ return AVERROR_PATCHWELCOME; }