static int nuv_packet(AVFormatContext *s, AVPacket *pkt) { NUVContext *ctx = s->priv_data; ByteIOContext *pb = s->pb; uint8_t hdr[HDRSIZE]; nuv_frametype frametype; int ret, size; while (!url_feof(pb)) { int copyhdrsize = ctx->rtjpg_video ? HDRSIZE : 0; uint64_t pos = url_ftell(pb); ret = get_buffer(pb, hdr, HDRSIZE); if (ret <= 0) return ret ? ret : -1; frametype = hdr[0]; size = PKTSIZE(AV_RL32(&hdr[8])); switch (frametype) { case NUV_EXTRADATA: if (!ctx->rtjpg_video) { url_fskip(pb, size); break; } case NUV_VIDEO: if (ctx->v_id < 0) { av_log(s, AV_LOG_ERROR, "Video packet in file without video stream!\n"); url_fskip(pb, size); break; } ret = av_new_packet(pkt, copyhdrsize + size); if (ret < 0) return ret; // HACK: we have no idea if it is a keyframe, // but if we mark none seeking will not work at all. pkt->flags |= PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = AV_RL32(&hdr[4]); pkt->stream_index = ctx->v_id; memcpy(pkt->data, hdr, copyhdrsize); ret = get_buffer(pb, pkt->data + copyhdrsize, size); return ret; case NUV_AUDIO: if (ctx->a_id < 0) { av_log(s, AV_LOG_ERROR, "Audio packet in file without audio stream!\n"); url_fskip(pb, size); break; } ret = av_get_packet(pb, pkt, size); pkt->flags |= PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = AV_RL32(&hdr[4]); pkt->stream_index = ctx->a_id; return ret; case NUV_SEEKP: // contains no data, size value is invalid break; default: url_fskip(pb, size); break; } } return AVERROR(EIO); }
/** * \brief attempts to read a timestamp from stream at the given stream position * \return timestamp if successfull and AV_NOPTS_VALUE if failure */ static int64_t nuv_read_dts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit) { NUVContext *ctx = s->priv_data; AVIOContext *pb = s->pb; uint8_t hdr[HDRSIZE]; nuv_frametype frametype; int size, key, idx; int64_t pos, dts; if (avio_seek(pb, *ppos, SEEK_SET) < 0) return AV_NOPTS_VALUE; if (!nuv_resync(s, pos_limit)) return AV_NOPTS_VALUE; while (!url_feof(pb) && avio_tell(pb) < pos_limit) { if (avio_read(pb, hdr, HDRSIZE) < HDRSIZE) return AV_NOPTS_VALUE; frametype = hdr[0]; size = PKTSIZE(AV_RL32(&hdr[8])); switch (frametype) { case NUV_SEEKP: break; case NUV_AUDIO: case NUV_VIDEO: if (frametype == NUV_VIDEO) { idx = ctx->v_id; key = hdr[2] == 0; } else { idx = ctx->a_id; key = 1; } if (stream_index == idx) { pos = avio_tell(s->pb) - HDRSIZE; dts = AV_RL32(&hdr[4]); // TODO - add general support in av_gen_search, so it adds positions after reading timestamps av_add_index_entry(s->streams[stream_index], pos, dts, size + HDRSIZE, 0, key ? AVINDEX_KEYFRAME : 0); *ppos = pos; return dts; } default: avio_skip(pb, size); break; } } return AV_NOPTS_VALUE; }
static int nuv_packet(AVFormatContext *s, AVPacket *pkt) { NUVContext *ctx = (NUVContext *)s->priv_data; ByteIOContext *pb = &s->pb; uint8_t hdr[HDRSIZE]; frametype_t frametype; int ret, size; while (!url_feof(pb)) { ret = get_buffer(pb, hdr, HDRSIZE); if (ret <= 0) return ret ? ret : -1; frametype = hdr[0]; size = PKTSIZE(LE_32(&hdr[8])); switch (frametype) { case NUV_VIDEO: case NUV_EXTRADATA: if (ctx->v_id < 0) { av_log(s, AV_LOG_ERROR, "Video packet in file without video stream!\n"); url_fskip(pb, size); break; } ret = av_new_packet(pkt, HDRSIZE + size); if (ret < 0) return ret; pkt->pos = url_ftell(pb); pkt->pts = LE_32(&hdr[4]); pkt->stream_index = ctx->v_id; memcpy(pkt->data, hdr, HDRSIZE); ret = get_buffer(pb, pkt->data + HDRSIZE, size); return ret; case NUV_AUDIO: if (ctx->a_id < 0) { av_log(s, AV_LOG_ERROR, "Audio packet in file without audio stream!\n"); url_fskip(pb, size); break; } ret = av_get_packet(pb, pkt, size); pkt->pts = LE_32(&hdr[4]); pkt->stream_index = ctx->a_id; return ret; case NUV_SEEKP: // contains no data, size value is invalid break; default: url_fskip(pb, size); break; } } return AVERROR_IO; }
/** * \brief read until we found all data needed for decoding * \param vst video stream of which to change parameters * \param ast video stream of which to change parameters * \param myth set if this is a MythTVVideo format file * \return 1 if all required codec data was found */ static int get_codec_data(ByteIOContext *pb, AVStream *vst, AVStream *ast, int myth) { nuv_frametype frametype; if (!vst && !myth) return 1; // no codec data needed while (!url_feof(pb)) { int size, subtype; frametype = get_byte(pb); switch (frametype) { case NUV_EXTRADATA: subtype = get_byte(pb); url_fskip(pb, 6); size = PKTSIZE(get_le32(pb)); if (vst && subtype == 'R') { vst->codec->extradata_size = size; vst->codec->extradata = av_malloc(size); get_buffer(pb, vst->codec->extradata, size); size = 0; if (!myth) return 1; } break; case NUV_MYTHEXT: url_fskip(pb, 7); size = PKTSIZE(get_le32(pb)); if (size != 128 * 4) break; get_le32(pb); // version if (vst) { vst->codec->codec_tag = get_le32(pb); vst->codec->codec_id = codec_get_id(codec_bmp_tags, vst->codec->codec_tag); if (vst->codec->codec_tag == MKTAG('R', 'J', 'P', 'G')) vst->codec->codec_id = CODEC_ID_NUV; } else url_fskip(pb, 4); if (ast) { ast->codec->codec_tag = get_le32(pb); ast->codec->sample_rate = get_le32(pb); ast->codec->bits_per_coded_sample = get_le32(pb); ast->codec->channels = get_le32(pb); ast->codec->codec_id = wav_codec_get_id(ast->codec->codec_tag, ast->codec->bits_per_coded_sample); ast->need_parsing = AVSTREAM_PARSE_FULL; } else url_fskip(pb, 4 * 4); size -= 6 * 4; url_fskip(pb, size); return 1; case NUV_SEEKP: size = 11; break; default: url_fskip(pb, 7); size = PKTSIZE(get_le32(pb)); break; } url_fskip(pb, size); } return 0; }
static int nuv_packet(AVFormatContext *s, AVPacket *pkt) { NUVContext *ctx = s->priv_data; AVIOContext *pb = s->pb; uint8_t hdr[HDRSIZE]; nuv_frametype frametype; int ret, size; while (!url_feof(pb)) { int copyhdrsize = ctx->rtjpg_video ? HDRSIZE : 0; uint64_t pos = avio_tell(pb); ret = avio_read(pb, hdr, HDRSIZE); if (ret < HDRSIZE) return ret < 0 ? ret : AVERROR(EIO); frametype = hdr[0]; size = PKTSIZE(AV_RL32(&hdr[8])); switch (frametype) { case NUV_EXTRADATA: if (!ctx->rtjpg_video) { avio_skip(pb, size); break; } case NUV_VIDEO: if (ctx->v_id < 0) { av_log(s, AV_LOG_ERROR, "Video packet in file without video stream!\n"); avio_skip(pb, size); break; } ret = av_new_packet(pkt, copyhdrsize + size); if (ret < 0) return ret; pkt->pos = pos; pkt->flags |= hdr[2] == 0 ? AV_PKT_FLAG_KEY : 0; pkt->pts = AV_RL32(&hdr[4]); pkt->stream_index = ctx->v_id; memcpy(pkt->data, hdr, copyhdrsize); ret = avio_read(pb, pkt->data + copyhdrsize, size); if (ret < 0) { av_free_packet(pkt); return ret; } if (ret < size) av_shrink_packet(pkt, copyhdrsize + ret); return 0; case NUV_AUDIO: if (ctx->a_id < 0) { av_log(s, AV_LOG_ERROR, "Audio packet in file without audio stream!\n"); avio_skip(pb, size); break; } ret = av_get_packet(pb, pkt, size); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = AV_RL32(&hdr[4]); pkt->stream_index = ctx->a_id; if (ret < 0) return ret; return 0; case NUV_SEEKP: // contains no data, size value is invalid break; default: avio_skip(pb, size); break; } } return AVERROR(EIO); }
/** * @brief read until we found all data needed for decoding * @param vst video stream of which to change parameters * @param ast video stream of which to change parameters * @param myth set if this is a MythTVVideo format file * @return 0 or AVERROR code */ static int get_codec_data(AVIOContext *pb, AVStream *vst, AVStream *ast, int myth) { nuv_frametype frametype; if (!vst && !myth) return 1; // no codec data needed while (!avio_feof(pb)) { int size, subtype; frametype = avio_r8(pb); switch (frametype) { case NUV_EXTRADATA: subtype = avio_r8(pb); avio_skip(pb, 6); size = PKTSIZE(avio_rl32(pb)); if (vst && subtype == 'R') { if (vst->codec->extradata) { av_freep(&vst->codec->extradata); vst->codec->extradata_size = 0; } if (ff_get_extradata(vst->codec, pb, size) < 0) return AVERROR(ENOMEM); size = 0; if (!myth) return 0; } break; case NUV_MYTHEXT: avio_skip(pb, 7); size = PKTSIZE(avio_rl32(pb)); if (size != 128 * 4) break; avio_rl32(pb); // version if (vst) { vst->codec->codec_tag = avio_rl32(pb); vst->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, vst->codec->codec_tag); if (vst->codec->codec_tag == MKTAG('R', 'J', 'P', 'G')) vst->codec->codec_id = AV_CODEC_ID_NUV; } else avio_skip(pb, 4); if (ast) { int id; ast->codec->codec_tag = avio_rl32(pb); ast->codec->sample_rate = avio_rl32(pb); ast->codec->bits_per_coded_sample = avio_rl32(pb); ast->codec->channels = avio_rl32(pb); ast->codec->channel_layout = 0; id = ff_wav_codec_get_id(ast->codec->codec_tag, ast->codec->bits_per_coded_sample); if (id == AV_CODEC_ID_NONE) { id = ff_codec_get_id(nuv_audio_tags, ast->codec->codec_tag); if (id == AV_CODEC_ID_PCM_S16LE) id = ff_get_pcm_codec_id(ast->codec->bits_per_coded_sample, 0, 0, ~1); } ast->codec->codec_id = id; ast->need_parsing = AVSTREAM_PARSE_FULL; } else avio_skip(pb, 4 * 4); size -= 6 * 4; avio_skip(pb, size); return 0; case NUV_SEEKP: size = 11; break; default: avio_skip(pb, 7); size = PKTSIZE(avio_rl32(pb)); break; } avio_skip(pb, size); } return 0; }
/** * \brief read until we found all data needed for decoding * \param vst video stream of which to change parameters * \param ast video stream of which to change parameters * \param myth set if this is a MythTVVideo format file * \return 1 if all required codec data was found */ static int get_codec_data(AVIOContext *pb, AVStream *vst, AVStream *ast, int myth) { nuv_frametype frametype; if (!vst && !myth) return 1; // no codec data needed while (!url_feof(pb)) { int size, subtype; frametype = avio_r8(pb); switch (frametype) { case NUV_EXTRADATA: subtype = avio_r8(pb); avio_seek(pb, 6, SEEK_CUR); size = PKTSIZE(avio_rl32(pb)); if (vst && subtype == 'R') { vst->codec->extradata_size = size; vst->codec->extradata = av_malloc(size); avio_read(pb, vst->codec->extradata, size); size = 0; if (!myth) return 1; } break; case NUV_MYTHEXT: avio_seek(pb, 7, SEEK_CUR); size = PKTSIZE(avio_rl32(pb)); if (size != 128 * 4) break; avio_rl32(pb); // version if (vst) { vst->codec->codec_tag = avio_rl32(pb); vst->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, vst->codec->codec_tag); if (vst->codec->codec_tag == MKTAG('R', 'J', 'P', 'G')) vst->codec->codec_id = CODEC_ID_NUV; } else avio_seek(pb, 4, SEEK_CUR); if (ast) { ast->codec->codec_tag = avio_rl32(pb); ast->codec->sample_rate = avio_rl32(pb); ast->codec->bits_per_coded_sample = avio_rl32(pb); ast->codec->channels = avio_rl32(pb); ast->codec->codec_id = ff_wav_codec_get_id(ast->codec->codec_tag, ast->codec->bits_per_coded_sample); ast->need_parsing = AVSTREAM_PARSE_FULL; } else avio_seek(pb, 4 * 4, SEEK_CUR); size -= 6 * 4; avio_seek(pb, size, SEEK_CUR); return 1; case NUV_SEEKP: size = 11; break; default: avio_seek(pb, 7, SEEK_CUR); size = PKTSIZE(avio_rl32(pb)); break; } avio_seek(pb, size, SEEK_CUR); } return 0; }