使用h264_rkmpp作为解码器,从avcodec_receive_frame返回的frme->pkt_size一直为-1的解决方法,大家避坑 #107

Closed
opened 2025-12-23 10:33:12 +01:00 by backuprepo · 3 comments
Owner

Originally created by @wzw88486969 on GitHub (Oct 15, 2024).


AVCodec *video_codec = avcodec_find_decoder_by_name("h264_rkmpp"); 
AVBSFContext *bsf_ctx;
int is_annexb;
//-------------------------------------------------------------
for (int i = 0; i < ifmt_ctx->nb_streams; i++) {
	if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
		is_annexb = strcmp(av_fourcc2str(ifmt_ctx->streams[i]->codecpar->codec_tag), "avc1") == 0 ? 0 : 1;
	}
}


fprintf(stdout, "is_annexb=%d\n", is_annexb);  
if (!is_annexb) {
    if (ret = open_bitstream_filter(ifmt_ctx->streams[video_stream_index], "h264_mp4toannexb") < 0) {
       fprintf(stderr, "open_bitstream_filter failed, ret=%d\n", ret);  
       goto end;
    }
}
//-------------------------------------------------------------------
while (av_read_frame(ifmt_ctx, pkt) >= 0) {
    if (pkt->stream_index == video_stream_index) {
        if (is_annexb) {
			
        } else {
            ret = filter_stream(bsf_ctx, pkt);
        }
        
	AVCodecParameters *codecpar = p->frtCtx->streams[i]->codecpar;
	if((pkt->data[4] & 0x1f) == 5) && codecpar->extradata_size > 0){
		//store sps pps I frame 
		AVPacket tmppacket;
		char buffer[1024 * 1024];
		memcpy(buffer, codecpar->extradata, codecpar->extradata_size);
		memcpy(buffer + codecpar->extradata_size, pkt->data, pkt->size);

		tmppacket.data = (uint8_t *)buffer;
		tmppacket.size = codecpar->extradata_size + pkt->size;
		
		decode_simple(tmppacket);
	}else {
		decode_simple(pkt);
	}

    } else {
        fprintf(stdout, "read a packet, not a video frame\n");
    }
    av_packet_unref(pkt);
}

//---------------------------------------------------------

int open_bitstream_filter(AVStream *stream, const char *name) {
    int ret = 0;
    const AVBitStreamFilter *filter = av_bsf_get_by_name(name);
    if (!filter) {
        ret = -1;
        fprintf(stderr, "Unknow bitstream filter.\n");
    }
    if((ret = av_bsf_alloc(filter, &bsf_ctx) < 0)) {
        fprintf(stderr, "av_bsf_alloc failed\n");
        return ret;
    }
    if ((ret = avcodec_parameters_copy(bsf_ctx->par_in, stream->codecpar)) < 0) {
        fprintf(stderr, "avcodec_parameters_copy failed, ret=%d\n", ret);
        return ret;
    }
    if ((ret = av_bsf_init(bsf_ctx)) < 0) {
        fprintf(stderr, "av_bsf_init failed, ret=%d\n", ret);       
        return ret;
    }
    return ret;
}
int close_bitstream_filter(){
    if(is_annexb){
        if (bsf_ctx)
            av_bsf_free(&bsf_ctx);
    }
}

int filter_stream( AVPacket *pkt) {
    int ret = 0;
    if (ret = av_bsf_send_packet(bsf_ctx, pkt) < 0) {
        fprintf(stderr, "av_bsf_send_packet failed, ret=%d\n", ret);
        return ret;
    } 
    while ((ret = av_bsf_receive_packet(bsf_ctx, pkt) == 0)) {
        // ret = write_output(of, pkt); 
        // av_packet_unref(pkt);
        // if (ret < 0) return ret;
    }
    
    //if (ret == AVERROR(EAGAIN)) return 0;
    
    return ret;
}

Originally created by @wzw88486969 on GitHub (Oct 15, 2024). ```c AVCodec *video_codec = avcodec_find_decoder_by_name("h264_rkmpp"); AVBSFContext *bsf_ctx; int is_annexb; //------------------------------------------------------------- for (int i = 0; i < ifmt_ctx->nb_streams; i++) { if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { is_annexb = strcmp(av_fourcc2str(ifmt_ctx->streams[i]->codecpar->codec_tag), "avc1") == 0 ? 0 : 1; } } fprintf(stdout, "is_annexb=%d\n", is_annexb); if (!is_annexb) { if (ret = open_bitstream_filter(ifmt_ctx->streams[video_stream_index], "h264_mp4toannexb") < 0) { fprintf(stderr, "open_bitstream_filter failed, ret=%d\n", ret); goto end; } } //------------------------------------------------------------------- while (av_read_frame(ifmt_ctx, pkt) >= 0) { if (pkt->stream_index == video_stream_index) { if (is_annexb) { } else { ret = filter_stream(bsf_ctx, pkt); } AVCodecParameters *codecpar = p->frtCtx->streams[i]->codecpar; if((pkt->data[4] & 0x1f) == 5) && codecpar->extradata_size > 0){ //store sps pps I frame AVPacket tmppacket; char buffer[1024 * 1024]; memcpy(buffer, codecpar->extradata, codecpar->extradata_size); memcpy(buffer + codecpar->extradata_size, pkt->data, pkt->size); tmppacket.data = (uint8_t *)buffer; tmppacket.size = codecpar->extradata_size + pkt->size; decode_simple(tmppacket); }else { decode_simple(pkt); } } else { fprintf(stdout, "read a packet, not a video frame\n"); } av_packet_unref(pkt); } //--------------------------------------------------------- int open_bitstream_filter(AVStream *stream, const char *name) { int ret = 0; const AVBitStreamFilter *filter = av_bsf_get_by_name(name); if (!filter) { ret = -1; fprintf(stderr, "Unknow bitstream filter.\n"); } if((ret = av_bsf_alloc(filter, &bsf_ctx) < 0)) { fprintf(stderr, "av_bsf_alloc failed\n"); return ret; } if ((ret = avcodec_parameters_copy(bsf_ctx->par_in, stream->codecpar)) < 0) { fprintf(stderr, "avcodec_parameters_copy failed, ret=%d\n", ret); return ret; } if ((ret = av_bsf_init(bsf_ctx)) < 0) { fprintf(stderr, "av_bsf_init failed, ret=%d\n", ret); return ret; } return ret; } int close_bitstream_filter(){ if(is_annexb){ if (bsf_ctx) av_bsf_free(&bsf_ctx); } } int filter_stream( AVPacket *pkt) { int ret = 0; if (ret = av_bsf_send_packet(bsf_ctx, pkt) < 0) { fprintf(stderr, "av_bsf_send_packet failed, ret=%d\n", ret); return ret; } while ((ret = av_bsf_receive_packet(bsf_ctx, pkt) == 0)) { // ret = write_output(of, pkt); // av_packet_unref(pkt); // if (ret < 0) return ret; } //if (ret == AVERROR(EAGAIN)) return 0; return ret; } ```
backuprepo 2025-12-23 10:33:12 +01:00
  • closed this issue
  • added the
    question
    label
Author
Owner

@nyanmisaka commented on GitHub (Oct 15, 2024):

The h26x_rkmpp decoder declaration already registers the required bitsteam filters, but the decoder itself is not responsible for filtering bitstream, the user/fftools must do this themselves.

5ddd3d4f5b/libavcodec/rkmppdec.c (L954-L980)

Search av_bsf_ in fftools/ffmpeg_demux.c and see how to use it.

@nyanmisaka commented on GitHub (Oct 15, 2024): The `h26x_rkmpp` decoder declaration already registers the required bitsteam filters, but the decoder itself is not responsible for filtering bitstream, the user/fftools must do this themselves. https://github.com/nyanmisaka/ffmpeg-rockchip/blob/5ddd3d4f5b98c4abd7e2e3633c35ee4a93f2f33e/libavcodec/rkmppdec.c#L954-L980 Search `av_bsf_` in `fftools/ffmpeg_demux.c` and see how to use it.
Author
Owner

@wzw88486969 commented on GitHub (Oct 16, 2024):

I always have a problem with him pulling stream decoding, and I found this problem by debugging the MPP library separately, and I am now preprocessing it in advance outside, and then decoding ffmpeg

@wzw88486969 commented on GitHub (Oct 16, 2024): I always have a problem with him pulling stream decoding, and I found this problem by debugging the MPP library separately, and I am now preprocessing it in advance outside, and then decoding ffmpeg
Author
Owner

@nyanmisaka commented on GitHub (Oct 16, 2024):

Closing as it's not a ffmpeg issue.

@nyanmisaka commented on GitHub (Oct 16, 2024): Closing as it's not a ffmpeg issue.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: starred/ffmpeg-rockchip#107
No description provided.