[FFmpeg-devel] [PATCH 2/2] MxPEG decoder

Anatoly Nenashev anatoly.nenashev
Mon Nov 1 21:56:21 CET 2010


On 01.11.2010 22:10, Michael Niedermayer wrote:
> On Mon, Nov 01, 2010 at 09:42:06PM +0300, Anatoly Nenashev wrote:
>    
>> On 01.11.2010 15:55, Michael Niedermayer wrote:
>>      
>>> On Mon, Nov 01, 2010 at 11:52:54AM +0300, Anatoly Nenashev wrote:
>>>
>>>        
>>>> On 01.11.2010 03:31, Michael Niedermayer wrote:
>>>>
>>>>          
>>>>> On Mon, Nov 01, 2010 at 02:56:50AM +0300, Anatoly Nenashev wrote:
>>>>>
>>>>>
>>>>>            
>>>>>> On 01.11.2010 01:17, Michael Niedermayer wrote:
>>>>>>
>>>>>>
>>>>>>              
>>>>>>> On Sun, Oct 31, 2010 at 09:23:13PM +0300, Anatoly Nenashev wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                
>>>>>>>> Patch for .mxg demuxer
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>                  
>>>>>>> [...]
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                
>>>>>>>> +static int mxg_read_header(AVFormatContext *s, AVFormatParameters *ap)
>>>>>>>> +{
>>>>>>>> +    AVStream *video_st = 0, *audio_st = 0;
>>>>>>>> +    MXGContext *mxg = s->priv_data;
>>>>>>>> +
>>>>>>>> +    /* video parameters will be extracted from the compressed bitstream */
>>>>>>>> +    video_st = av_new_stream(s, VIDEO_STREAM_INDEX);
>>>>>>>> +    if (!video_st)
>>>>>>>> +        return AVERROR(ENOMEM);
>>>>>>>> +    video_st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
>>>>>>>> +    video_st->codec->codec_id = CODEC_ID_MXPEG;
>>>>>>>> +    av_set_pts_info(video_st, 64, 1, 1000000);
>>>>>>>> +
>>>>>>>> +    audio_st = av_new_stream(s, AUDIO_STREAM_INDEX);
>>>>>>>> +    if (!audio_st)
>>>>>>>> +        return AVERROR(ENOMEM);
>>>>>>>> +    audio_st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
>>>>>>>> +    audio_st->codec->codec_id = CODEC_ID_PCM_ALAW;
>>>>>>>> +    audio_st->codec->channels = 1;
>>>>>>>> +    audio_st->codec->sample_rate = 8000;
>>>>>>>> +    audio_st->codec->bits_per_coded_sample = 8;
>>>>>>>> +    audio_st->codec->block_align = 1;
>>>>>>>> +
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>                  
>>>>>>>
>>>>>>>                
>>>>>>>> +    mxg->buffer = (uint8_t*) av_malloc(DEFAULT_PACKET_SIZE);
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>                  
>>>>>>> unneeded cast
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                
>>>>>> removed
>>>>>>
>>>>>>
>>>>>>
>>>>>>              
>>>>>>> [...]
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                
>>>>>>>> +        if (mxg->found_video_packet) {
>>>>>>>> +            mxg->buffer[mxg->current_pos++] = data;
>>>>>>>> +            if (mxg->state == 0xfffe) {
>>>>>>>> +                int size = get_be16(s->pb);
>>>>>>>> +                if (url_feof(s->pb) || url_ferror(s->pb))
>>>>>>>> +                    return AVERROR_EOF;
>>>>>>>> +                mxg->buffer = av_fast_realloc(mxg->buffer,&mxg->buffer_size,
>>>>>>>> +                                              mxg->current_pos + size);
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>                  
>>>>>>> here the + and similar at other points can overflow and lead to realloc to a
>>>>>>> too small buffer
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                
>>>>>> fixed
>>>>>>
>>>>>>
>>>>>>
>>>>>>              
>>>>>>> [...]
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                
>>>>>>>> +            if (mxg->current_pos>= mxg->buffer_size) {
>>>>>>>> +                mxg->buffer = (uint8_t*) av_fast_realloc(mxg->buffer,&mxg->buffer_size,
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>                  
>>>>>>> unneeded cast
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                
>>>>>> removed
>>>>>>
>>>>>>
>>>>>>
>>>>>>              
>>>>> [...]
>>>>>
>>>>>
>>>>>            
>>>>>> +static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt)
>>>>>> +{
>>>>>> +    int ret, size;
>>>>>> +    MXGContext *mxg = s->priv_data;
>>>>>> +
>>>>>> +    while(!url_feof(s->pb)&&    !url_ferror(s->pb)) {
>>>>>> +        uint8_t data;
>>>>>> +        int found_frame_end = 0;
>>>>>> +
>>>>>> +        if (mxg->state == 0xffed) {
>>>>>> +            size = get_be16(s->pb);
>>>>>> +            if (url_feof(s->pb) || url_ferror(s->pb))
>>>>>> +                return AVERROR_EOF;
>>>>>> +            if (size<= 14)
>>>>>> +                return AVERROR(EINVAL);
>>>>>> +            url_fskip(s->pb, 12);
>>>>>> +            if (url_feof(s->pb))
>>>>>> +                return AVERROR_EOF;
>>>>>> +            size -= 14;
>>>>>> +            ret = av_get_packet(s->pb, pkt, size);
>>>>>> +            if (ret<    0)
>>>>>> +                return ret;
>>>>>> +
>>>>>> +            pkt->stream_index = AUDIO_STREAM_INDEX;
>>>>>> +            mxg->state = 0;
>>>>>> +
>>>>>> +            return pkt->size;
>>>>>> +        }
>>>>>> +
>>>>>> +        data = get_byte(s->pb);
>>>>>> +        mxg->state = (mxg->state<<    8) | data;
>>>>>> +
>>>>>> +        if (mxg->found_video_packet) {
>>>>>> +            mxg->buffer[mxg->current_pos++] = data;
>>>>>> +            if (mxg->state == 0xfffe) {
>>>>>> +                int size = get_be16(s->pb);
>>>>>> +                if (url_feof(s->pb) || url_ferror(s->pb))
>>>>>> +                    return AVERROR_EOF;
>>>>>> +
>>>>>> +                if (mxg->current_pos>    mxg->current_pos + size)
>>>>>> +                {
>>>>>> +                    av_log(s, AV_LOG_ERROR, "buffer overflow\n");
>>>>>> +                    return AVERROR(ENOMEM);
>>>>>> +                }
>>>>>> +                mxg->buffer = av_fast_realloc(mxg->buffer,&mxg->buffer_size,
>>>>>> +                                              mxg->current_pos + size);
>>>>>> +                if (!mxg->buffer) {
>>>>>> +                    av_log(s, AV_LOG_ERROR, "mxg demuxer error in av_fast_realloc()\n");
>>>>>> +                    return AVERROR(ENOMEM);
>>>>>> +                }
>>>>>> +                if (size<    2) {
>>>>>> +                    av_log(s, AV_LOG_ERROR, "wrong comment buffer size\n");
>>>>>> +                    return AVERROR(EINVAL);
>>>>>> +                }
>>>>>> +                mxg->buffer[mxg->current_pos++] = size>>    8;
>>>>>> +                mxg->buffer[mxg->current_pos++] = size&    0xff;
>>>>>> +
>>>>>> +                ret = get_buffer(s->pb, mxg->buffer + mxg->current_pos, size - 2);
>>>>>> +                if (ret<    0)
>>>>>> +                    return ret;
>>>>>> +                if (ret>= 16&&    !strncmp(mxg->buffer + mxg->current_pos, "MXF", 3)) {
>>>>>> +                    mxg->dts = AV_RL64(mxg->buffer + mxg->current_pos + 8);
>>>>>> +                }
>>>>>> +                mxg->current_pos += ret;
>>>>>> +                mxg->state = 0;
>>>>>> +            } else if (mxg->state == 0xffd9) {
>>>>>> +                found_frame_end = mxg->current_pos;
>>>>>> +                mxg->current_pos = 0;
>>>>>> +                mxg->found_video_packet = 0;
>>>>>> +            } else if (mxg->state == 0xffd8) {
>>>>>> +                //emulating frame end
>>>>>> +                found_frame_end = mxg->current_pos - 2;
>>>>>> +                mxg->current_pos = 2;
>>>>>> +                mxg->found_video_packet = 1;
>>>>>> +            } else if (mxg->state == 0xffed) {
>>>>>> +                //emulating frame end
>>>>>> +                found_frame_end = mxg->current_pos - 2;
>>>>>> +                mxg->current_pos = 0;
>>>>>> +                mxg->found_video_packet = 0;
>>>>>> +            }
>>>>>> +
>>>>>> +            if (found_frame_end) {
>>>>>> +                ret = av_new_packet(pkt, found_frame_end);
>>>>>> +                if (ret<    0)
>>>>>> +                    return ret;
>>>>>> +                memcpy(pkt->data, mxg->buffer, found_frame_end);
>>>>>> +                pkt->stream_index = VIDEO_STREAM_INDEX;
>>>>>> +                pkt->dts = mxg->dts;
>>>>>> +                return pkt->size;
>>>>>> +            }
>>>>>> +
>>>>>> +            if (mxg->current_pos>= mxg->buffer_size) {
>>>>>> +                if (mxg->current_pos>    mxg->current_pos + DEFAULT_PACKET_SIZE)
>>>>>> +                {
>>>>>> +                    av_log(s, AV_LOG_ERROR, "buffer overflow\n");
>>>>>> +                    return AVERROR(ENOMEM);
>>>>>> +                }
>>>>>> +                mxg->buffer = av_fast_realloc(mxg->buffer,&mxg->buffer_size,
>>>>>> +                                              mxg->current_pos + DEFAULT_PACKET_SIZE);
>>>>>> +                if (!mxg->buffer) {
>>>>>> +                    av_log(s, AV_LOG_ERROR, "mxg demuxer error in av_fast_realloc()\n");
>>>>>> +                    return AVERROR(ENOMEM);
>>>>>> +                }
>>>>>> +            }
>>>>>> +        } else if (mxg->state == 0xffd8){
>>>>>> +            mxg->found_video_packet = 1;
>>>>>> +        }
>>>>>>
>>>>>>
>>>>>>              
>>>>> This loop is a bit oddly structured, is there a reason for this?
>>>>> id expect it to be more of the form
>>>>> while {
>>>>> state= (state<<8) + ...
>>>>>
>>>>> if(state ==)
>>>>> else if
>>>>> else if
>>>>> else
>>>>> }
>>>>>
>>>>> but its kind of convoluted with the audio code being before the state update
>>>>> then found_video_packet=1 and checks for that
>>>>>
>>>>>
>>>>>
>>>>>            
>>>> Reimplemented. I hope that new version is more canonical.:-)
>>>>
>>>>          
>>> no its the same
>>> id like to understand why it is so convolutedly written if there is a reason
>>> why this is needed
>>> If its really needed this has to be documented so someone doesnt waste time
>>> rewriting it to half the code.
>>> And if there is no reason it should be simplified
>>>
>>>
>>>        
>> The principal reason consists in the following. If demuxer yet hasn't
>> found a starting marker for package video it should check much less
>> conditions, than in other case. Moreover in the second case it should
>> copy data from incoming stream into the internal buffer because we don't
>> know the size of video packet. That's why I have divided these two cases
>> in a program code in hope that so will be faster.
>>      
> I thought there is just audio and video
> What you say makes one belive that there are significant amounts of other
> things, besides
>    
Yes, this is that case. If the data is received from http they can 
contain some additional information in the beginning of each frame like this
0019fa0: 5454 d5d7 d6d6 d50d 0a2d 2d4d 4f42 4f54  TT.......--MOBOT
0019fb0: 4958 5f46 6173 745f 5365 7276 6572 7075  IX_Fast_Serverpu
0019fc0: 7368 0d0a 436f 6e74 656e 742d 7479 7065  sh..Content-type
0019fd0: 3a20 696d 6167 652f 6a70 6567 0d0a 0d0a  : image/jpeg....
0019fe0: ffd8 ffe0 0010 4a46 4946 0001 0100 0001  ......JFIF......
.........




More information about the ffmpeg-devel mailing list