0

I have a video file in MOV format. This file contains EIA608 subtitles. I use ffprobe to see the contents of all packets. For FFmpeg 4.3.1, I get the data of the first subtitle packet according to the file content at the offset specified for this packet, but for FFmpeg 4.4 and higher, I get "corrupted" data from the same packet. The beginning is cut off, the characters "0xfc" are added and the packet size is different. For packets of other types (video, audio, data), the result is the same for all versions of FFmpeg and exactly matches the contents of the file. I get the same result when using the av_read_frame() function call in my code with different versions of FFmpeg. Why does this happen with subtitle packets? What has changed in FFmpeg with the transition to version 4.4 and higher? What do I not know or do not understand?

The file content at packet position (position = 9723 = 0x25fb): The file content at packet position (position = 9723 = 0x25fb)

FFmpeg 4.3.1 ffprobe result for the first subtitle packet: FFmpeg 4.3.1 ffprobe result for the first subtitle packet

FFmpeg 4.4 and higher ffprobe result for the first subtitle packet: FFmpeg 4.4 and higher ffprobe result for the first subtitle packet

UPDATE: I found that since version 4.4. when reading a EIA608 subtitle packet for the MOV format, the get_eia608_packet() function has been added (mov_read_packet() used inside of av_read_frame(), get_eia608_packet() used inside of mov_read_packet()). But I don't understand for what purpose it was done. Can someone explain to me? As FFmpeg says about av_read_frame(): "This function returns what is stored in the file, and does not validate that what is there are valid frames for the decoder. It will split what is stored in the file into frames and return one for each call. It will not omit invalid data between valid frames so as to give the decoder the maximum information possible for decoding." av_read_frame() description

libavformat/mov.c:

static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int size)
{
    int new_size, ret;

    if (size <= 8)
        return AVERROR_INVALIDDATA;
    new_size = ((size - 8) / 2) * 3;
    ret = av_new_packet(pkt, new_size);
    if (ret < 0)
        return ret;

    avio_skip(pb, 8);
    for (int j = 0; j < new_size; j += 3) {
        pkt->data[j] = 0xFC;
        pkt->data[j+1] = avio_r8(pb);
        pkt->data[j+2] = avio_r8(pb);
    }

    return 0;
}

static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
{
...
if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8)
            ret = get_eia608_packet(sc->pb, pkt, sample->size);
        else
            ret = av_get_packet(sc->pb, pkt, sample->size);
...
}
Elija
  • 91
  • 6

0 Answers0