Ejemplo n.º 1
0
static int lrc_write_header(AVFormatContext *s)
{
    const AVDictionaryEntry *metadata_item;

    if(s->nb_streams != 1 ||
       s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
        av_log(s, AV_LOG_ERROR,
               "LRC supports only a single subtitle stream.\n");
        return AVERROR(EINVAL);
    }
    if(s->streams[0]->codecpar->codec_id != AV_CODEC_ID_SUBRIP &&
       s->streams[0]->codecpar->codec_id != AV_CODEC_ID_TEXT) {
        av_log(s, AV_LOG_ERROR, "Unsupported subtitle codec: %s\n",
               avcodec_get_name(s->streams[0]->codecpar->codec_id));
        return AVERROR(EINVAL);
    }
    avpriv_set_pts_info(s->streams[0], 64, 1, 100);

    ff_standardize_creation_time(s);
    ff_metadata_conv_ctx(s, ff_lrc_metadata_conv, NULL);
    if(!(s->flags & AVFMT_FLAG_BITEXACT)) { // avoid breaking regression tests
        /* LRC provides a metadata slot for specifying encoder version
         * in addition to encoder name. We will store LIBAVFORMAT_VERSION
         * to it.
         */
        av_dict_set(&s->metadata, "ve", AV_STRINGIFY(LIBAVFORMAT_VERSION), 0);
    } else {
        av_dict_set(&s->metadata, "ve", NULL, 0);
    }
    for(metadata_item = NULL;
       (metadata_item = av_dict_get(s->metadata, "", metadata_item,
                                    AV_DICT_IGNORE_SUFFIX));) {
        char *delim;
        if(!metadata_item->value[0]) {
            continue;
        }
        while((delim = strchr(metadata_item->value, '\n'))) {
            *delim = ' ';
        }
        while((delim = strchr(metadata_item->value, '\r'))) {
            *delim = ' ';
        }
        avio_printf(s->pb, "[%s:%s]\n",
                    metadata_item->key, metadata_item->value);
    }
    avio_printf(s->pb, "\n");
    return 0;
}
Ejemplo n.º 2
0
static int lrc_read_header(AVFormatContext *s)
{
    LRCContext *lrc = s->priv_data;
    AVBPrint line;
    AVStream *st;

    st = avformat_new_stream(s, NULL);
    if(!st) {
        return AVERROR(ENOMEM);
    }
    avpriv_set_pts_info(st, 64, 1, 1000);
    lrc->ts_offset = 0;
    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
    st->codec->codec_id   = AV_CODEC_ID_TEXT;
    av_bprint_init(&line, 0, AV_BPRINT_SIZE_UNLIMITED);

    while(!url_feof(s->pb)) {
        int64_t pos = read_line(&line, s->pb);
        int64_t header_offset = find_header(line.str);
        if(header_offset >= 0) {
            char *comma_offset = strchr(line.str, ':');
            if(comma_offset) {
                char *right_bracket_offset = strchr(line.str, ']');
                if(!right_bracket_offset) {
                    continue;
                }

                *right_bracket_offset = *comma_offset = '\0';
                if(strcmp(line.str + 1, "offset") ||
                   sscanf(comma_offset + 1, "%"SCNd64, &lrc->ts_offset) != 1) {
                    av_dict_set(&s->metadata, line.str + 1, comma_offset + 1, 0);
                }
                *comma_offset = ':';
                *right_bracket_offset = ']';
            }

        } else {
            AVPacket *sub;
            int64_t ts_start = AV_NOPTS_VALUE;
            int64_t ts_stroffset = 0;
            int64_t ts_stroffset_incr = 0;
            int64_t ts_strlength = count_ts(line.str);

            while((ts_stroffset_incr = read_ts(line.str + ts_stroffset,
                                               &ts_start)) != 0) {
                ts_stroffset += ts_stroffset_incr;
                sub = ff_subtitles_queue_insert(&lrc->q, line.str + ts_strlength,
                                                line.len - ts_strlength, 0);
                if(!sub) {
                    return AVERROR(ENOMEM);
                }
                sub->pos = pos;
                sub->pts = ts_start - lrc->ts_offset;
                sub->duration = -1;
            }
        }
    }
    ff_subtitles_queue_finalize(&lrc->q);
    ff_metadata_conv_ctx(s, NULL, ff_lrc_metadata_conv);
    return 0;
}
Ejemplo n.º 3
0
/* wav input */
static int wav_read_header(AVFormatContext *s,
                           AVFormatParameters *ap)
{
    int64_t size, av_uninit(data_size);
    int64_t sample_count=0;
    int rf64;
    unsigned int tag;
    AVIOContext *pb = s->pb;
    AVStream *st;
    WAVContext *wav = s->priv_data;
    int ret, got_fmt = 0;
    int64_t next_tag_ofs, data_ofs = -1;
    int min_samples_est0=0;
	int min_samples_est1=0;
	unsigned char bit_per_sample = 0;
    /* check RIFF header */
    tag = avio_rl32(pb);

    rf64 = tag == MKTAG('R', 'F', '6', '4');
    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
        return -1;
    avio_rl32(pb); /* file size */
    tag = avio_rl32(pb);
    if (tag != MKTAG('W', 'A', 'V', 'E'))
        return -1;

    if (rf64) {
        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
            return -1;
        size = avio_rl32(pb);
        if (size < 24)
            return -1;
        avio_rl64(pb); /* RIFF size */
        data_size = avio_rl64(pb);
        sample_count = avio_rl64(pb);
        if (data_size < 0 || sample_count < 0) {
            av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in "
                   "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n",
                   data_size, sample_count);
            return AVERROR_INVALIDDATA;
        }
        avio_skip(pb, size - 24); /* skip rest of ds64 chunk */
    }

    for (;;) {
        size = next_tag(pb, &tag);
        next_tag_ofs = avio_tell(pb) + size;

        if (url_feof(pb))
            break;

        switch (tag) {
        case MKTAG('f', 'm', 't', ' '):
            /* only parse the first 'fmt ' tag found */
            if (!got_fmt && (ret = wav_parse_fmt_tag(s, size, &st) < 0)) {
                return ret;
            } else if (got_fmt)
                av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n");

            got_fmt = 1;
            break;
        case MKTAG('d', 'a', 't', 'a'):
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR, "found no 'fmt ' tag before the 'data' tag\n");
                return AVERROR_INVALIDDATA;
            }

            if (rf64) {
                next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
            } else {
                data_size = size;
                next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
            }

            data_ofs = avio_tell(pb);

            /* don't look for footer metadata if we can't seek or if we don't
             * know where the data tag ends
             */
            if (!pb->seekable || (!rf64 && !size))
                goto break_loop;
            break;
        case MKTAG('f','a','c','t'):
            if(!sample_count)
                sample_count = avio_rl32(pb);
            break;
        case MKTAG('b','e','x','t'):
            if ((ret = wav_parse_bext_tag(s, size)) < 0)
                return ret;
            break;
        }

        /* seek to next tag unless we know that we'll run into EOF */
        if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
            avio_seek(pb, next_tag_ofs, SEEK_SET) < 0) {
            break;
        }
    }
break_loop:
    if (data_ofs < 0) {
        av_log(s, AV_LOG_ERROR, "no 'data' tag found\n");
        return AVERROR_INVALIDDATA;
    }

    avio_seek(pb, data_ofs, SEEK_SET);
	bit_per_sample = av_get_bits_per_sample(st->codec->codec_id);
	if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id))
		sample_count = (data_size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
	if(bit_per_sample&&st->codec->channels&&st->codec->bit_rate){//PCM audio
		min_samples_est0 = (size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
	    min_samples_est1 = (size<<3) / st->codec->bit_rate * st->codec->sample_rate;
		if (sample_count){
	      if(sample_count <= min_samples_est0)//:indecate that sample_count is unvalid
	            st->duration = min_samples_est1;
			else
				st->duration = (min_samples_est1 > sample_count? min_samples_est1:sample_count);
	    }
	}	
	
    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);

    return 0;
}
Ejemplo n.º 4
0
/* wav input */
static int wav_read_header(AVFormatContext *s)
{
    int64_t size, av_uninit(data_size);
    int64_t sample_count = 0;
    int rf64;
    uint32_t tag;
    AVIOContext *pb      = s->pb;
    AVStream *st         = NULL;
    WAVDemuxContext *wav = s->priv_data;
    int ret, got_fmt = 0;
    int64_t next_tag_ofs, data_ofs = -1;

    /* check RIFF header */
    tag = avio_rl32(pb);

    rf64 = tag == MKTAG('R', 'F', '6', '4');
    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
        return AVERROR_INVALIDDATA;
    avio_rl32(pb); /* file size */
    tag = avio_rl32(pb);
    if (tag != MKTAG('W', 'A', 'V', 'E'))
        return AVERROR_INVALIDDATA;

    if (rf64) {
        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
            return AVERROR_INVALIDDATA;
        size = avio_rl32(pb);
        if (size < 16)
            return AVERROR_INVALIDDATA;
        avio_rl64(pb); /* RIFF size */

        data_size    = avio_rl64(pb);
        sample_count = avio_rl64(pb);

        if (data_size < 0 || sample_count < 0) {
            av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in "
                   "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n",
                   data_size, sample_count);
            return AVERROR_INVALIDDATA;
        }
        avio_skip(pb, size - 16); /* skip rest of ds64 chunk */
    }

    for (;;) {
        size         = next_tag(pb, &tag);
        next_tag_ofs = avio_tell(pb) + size;

        if (pb->eof_reached)
            break;

        switch (tag) {
        case MKTAG('f', 'm', 't', ' '):
            /* only parse the first 'fmt ' tag found */
            if (!got_fmt && (ret = wav_parse_fmt_tag(s, size, &st) < 0)) {
                return ret;
            } else if (got_fmt)
                av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n");

            got_fmt = 1;
            break;
        case MKTAG('d', 'a', 't', 'a'):
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR,
                       "found no 'fmt ' tag before the 'data' tag\n");
                return AVERROR_INVALIDDATA;
            }

            if (rf64) {
                next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
            } else {
                data_size    = size;
                next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
            }

            data_ofs = avio_tell(pb);

            /* don't look for footer metadata if we can't seek or if we don't
             * know where the data tag ends
             */
            if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || (!rf64 && !size))
                goto break_loop;
            break;
        case MKTAG('f', 'a', 'c', 't'):
            if (!sample_count)
                sample_count = avio_rl32(pb);
            break;
        case MKTAG('b', 'e', 'x', 't'):
            if ((ret = wav_parse_bext_tag(s, size)) < 0)
                return ret;
            break;
        case MKTAG('L', 'I', 'S', 'T'):
            if (size < 4) {
                av_log(s, AV_LOG_ERROR, "too short LIST");
                return AVERROR_INVALIDDATA;
            }
            switch (avio_rl32(pb)) {
            case MKTAG('I', 'N', 'F', 'O'):
                if ((ret = ff_read_riff_info(s, size - 4)) < 0)
                    return ret;
            }
            break;
        }

        /* seek to next tag unless we know that we'll run into EOF */
        if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
            wav_seek_tag(pb, next_tag_ofs, SEEK_SET) < 0) {
            break;
        }
    }

break_loop:
    if (data_ofs < 0) {
        av_log(s, AV_LOG_ERROR, "no 'data' tag found\n");
        return AVERROR_INVALIDDATA;
    }

    avio_seek(pb, data_ofs, SEEK_SET);

    if (!sample_count && st->codecpar->channels &&
        av_get_bits_per_sample(st->codecpar->codec_id))
        sample_count = (data_size << 3) /
                       (st->codecpar->channels *
                        (uint64_t)av_get_bits_per_sample(st->codecpar->codec_id));
    if (sample_count)
        st->duration = sample_count;

    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);

    return 0;
}
Ejemplo n.º 5
0
static int w64_read_header(AVFormatContext *s)
{
    int64_t size, data_ofs = 0;
    AVIOContext *pb      = s->pb;
    WAVDemuxContext *wav = s->priv_data;
    AVStream *st;
    uint8_t guid[16];
    int ret;

    avio_read(pb, guid, 16);
    if (memcmp(guid, ff_w64_guid_riff, 16))
        return AVERROR_INVALIDDATA;

    /* riff + wave + fmt + sizes */
    if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8)
        return AVERROR_INVALIDDATA;

    avio_read(pb, guid, 16);
    if (memcmp(guid, ff_w64_guid_wave, 16)) {
        av_log(s, AV_LOG_ERROR, "could not find wave guid\n");
        return AVERROR_INVALIDDATA;
    }

    wav->w64 = 1;

    st = avformat_new_stream(s, NULL);
    if (!st)
        return AVERROR(ENOMEM);

    while (!url_feof(pb)) {
        if (avio_read(pb, guid, 16) != 16)
            break;
        size = avio_rl64(pb);
        if (size <= 24 || INT64_MAX - size < avio_tell(pb))
            return AVERROR_INVALIDDATA;

        if (!memcmp(guid, ff_w64_guid_fmt, 16)) {
            /* subtract chunk header size - normal wav file doesn't count it */
            ret = ff_get_wav_header(pb, st->codec, size - 24);
            if (ret < 0)
                return ret;
            avio_skip(pb, FFALIGN(size, INT64_C(8)) - size);

            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
        } else if (!memcmp(guid, ff_w64_guid_fact, 16)) {
            int64_t samples;

            samples = avio_rl64(pb);
            if (samples > 0)
                st->duration = samples;
        } else if (!memcmp(guid, ff_w64_guid_data, 16)) {
            wav->data_end = avio_tell(pb) + size - 24;

            data_ofs = avio_tell(pb);
            if (!pb->seekable)
                break;

            avio_skip(pb, size - 24);
        } else if (!memcmp(guid, ff_w64_guid_summarylist, 16)) {
            int64_t start, end, cur;
            uint32_t count, chunk_size, i;

            start = avio_tell(pb);
            end = start + size;
            count = avio_rl32(pb);

            for (i = 0; i < count; i++) {
                char chunk_key[5], *value;

                if (url_feof(pb) || (cur = avio_tell(pb)) < 0 || cur > end - 8 /* = tag + size */)
                    break;

                chunk_key[4] = 0;
                avio_read(pb, chunk_key, 4);
                chunk_size = avio_rl32(pb);

                value = av_mallocz(chunk_size + 1);
                if (!value)
                    return AVERROR(ENOMEM);

                ret = avio_get_str16le(pb, chunk_size, value, chunk_size);
                avio_skip(pb, chunk_size - ret);

                av_dict_set(&s->metadata, chunk_key, value, AV_DICT_DONT_STRDUP_VAL);
            }

            avio_skip(pb, end - avio_tell(pb));
        } else {
            av_log(s, AV_LOG_DEBUG, "unknown guid: "FF_PRI_GUID"\n", FF_ARG_GUID(guid));
            avio_skip(pb, size - 24);
        }
    }

    if (!data_ofs)
        return AVERROR_EOF;

    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);

    handle_stream_probing(st);
    st->need_parsing = AVSTREAM_PARSE_FULL_RAW;

    avio_seek(pb, data_ofs, SEEK_SET);

    return 0;
}
Ejemplo n.º 6
0
/* wav input */
static int wav_read_header(AVFormatContext *s)
{
    int64_t size, av_uninit(data_size);
    int64_t sample_count = 0;
    int rf64;
    uint32_t tag;
    AVIOContext *pb      = s->pb;
    AVStream *st         = NULL;
    WAVDemuxContext *wav = s->priv_data;
    int ret, got_fmt = 0;
    int64_t next_tag_ofs, data_ofs = -1;

    wav->smv_data_ofs = -1;

    /* check RIFF header */
    tag = avio_rl32(pb);

    rf64 = tag == MKTAG('R', 'F', '6', '4');
    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
        return AVERROR_INVALIDDATA;
    avio_rl32(pb); /* file size */
    tag = avio_rl32(pb);
    if (tag != MKTAG('W', 'A', 'V', 'E'))
        return AVERROR_INVALIDDATA;

    if (rf64) {
        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
            return AVERROR_INVALIDDATA;
        size = avio_rl32(pb);
        if (size < 24)
            return AVERROR_INVALIDDATA;
        avio_rl64(pb); /* RIFF size */

        data_size    = avio_rl64(pb);
        sample_count = avio_rl64(pb);

        if (data_size < 0 || sample_count < 0) {
            av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in "
                   "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n",
                   data_size, sample_count);
            return AVERROR_INVALIDDATA;
        }
        avio_skip(pb, size - 24); /* skip rest of ds64 chunk */

    }

    for (;;) {
        AVStream *vst;
        size         = next_tag(pb, &tag);
        next_tag_ofs = avio_tell(pb) + size;

        if (url_feof(pb))
            break;

        switch (tag) {
        case MKTAG('f', 'm', 't', ' '):
            /* only parse the first 'fmt ' tag found */
            if (!got_fmt && (ret = wav_parse_fmt_tag(s, size, &st)) < 0) {
                return ret;
            } else if (got_fmt)
                av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n");

            got_fmt = 1;
            break;
        case MKTAG('d', 'a', 't', 'a'):
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR,
                       "found no 'fmt ' tag before the 'data' tag\n");
                return AVERROR_INVALIDDATA;
            }

            if (rf64) {
                next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
            } else {
                data_size    = size;
                next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
            }

            data_ofs = avio_tell(pb);

            /* don't look for footer metadata if we can't seek or if we don't
             * know where the data tag ends
             */
            if (!pb->seekable || (!rf64 && !size))
                goto break_loop;
            break;
        case MKTAG('f', 'a', 'c', 't'):
            if (!sample_count)
                sample_count = avio_rl32(pb);
            break;
        case MKTAG('b', 'e', 'x', 't'):
            if ((ret = wav_parse_bext_tag(s, size)) < 0)
                return ret;
            break;
        case MKTAG('S','M','V','0'):
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR, "found no 'fmt ' tag before the 'SMV0' tag\n");
                return AVERROR_INVALIDDATA;
            }
            // SMV file, a wav file with video appended.
            if (size != MKTAG('0','2','0','0')) {
                av_log(s, AV_LOG_ERROR, "Unknown SMV version found\n");
                goto break_loop;
            }
            av_log(s, AV_LOG_DEBUG, "Found SMV data\n");
            wav->smv_given_first = 0;
            vst = avformat_new_stream(s, NULL);
            if (!vst)
                return AVERROR(ENOMEM);
            avio_r8(pb);
            vst->id = 1;
            vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
            vst->codec->codec_id = AV_CODEC_ID_SMVJPEG;
            vst->codec->width  = avio_rl24(pb);
            vst->codec->height = avio_rl24(pb);
            vst->codec->extradata_size = 4;
            vst->codec->extradata = av_malloc(vst->codec->extradata_size +
                                              FF_INPUT_BUFFER_PADDING_SIZE);
            if (!vst->codec->extradata) {
                av_log(s, AV_LOG_ERROR, "Could not allocate extradata.\n");
                return AVERROR(ENOMEM);
            }
            size = avio_rl24(pb);
            wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3;
            avio_rl24(pb);
            wav->smv_block_size = avio_rl24(pb);
            avpriv_set_pts_info(vst, 32, 1, avio_rl24(pb));
            vst->duration = avio_rl24(pb);
            avio_rl24(pb);
            avio_rl24(pb);
            wav->smv_frames_per_jpeg = avio_rl24(pb);
            AV_WL32(vst->codec->extradata, wav->smv_frames_per_jpeg);
            wav->smv_cur_pt = 0;
            goto break_loop;
        case MKTAG('L', 'I', 'S', 'T'):
            if (size < 4) {
                av_log(s, AV_LOG_ERROR, "too short LIST tag\n");
                return AVERROR_INVALIDDATA;
            }
            switch (avio_rl32(pb)) {
            case MKTAG('I', 'N', 'F', 'O'):
                ff_read_riff_info(s, size - 4);
            }
            break;
        }

        /* seek to next tag unless we know that we'll run into EOF */
        if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
            wav_seek_tag(pb, next_tag_ofs, SEEK_SET) < 0) {
            break;
        }
    }

break_loop:
    if (data_ofs < 0) {
        av_log(s, AV_LOG_ERROR, "no 'data' tag found\n");
        return AVERROR_INVALIDDATA;
    }

    avio_seek(pb, data_ofs, SEEK_SET);

    if (!sample_count && st->codec->channels &&
        av_get_bits_per_sample(st->codec->codec_id) && wav->data_end <= avio_size(pb))
        sample_count = (data_size << 3) /
                       (st->codec->channels *
                        (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
    if (sample_count)
        st->duration = sample_count;

    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);

    return 0;
}