问题
In Android JNI, using ffmpeg with libx264
use below codes to encode and decode raw rgb data!. I should use swscale to convert rgb565 to yuv420p as required by H.264. But not clear about this conversion.Please help, where i am wrong, with regard the log i get!
Code for Encoding
codecinit()- called once(JNI wrapper function)
int Java_com_my_package_codecinit (JNIEnv *env, jobject thiz) {
avcodec_register_all();
codec = avcodec_find_encoder(AV_CODEC_ID_H264);//AV_CODEC_ID_MPEG1VIDEO);
if(codec->id == AV_CODEC_ID_H264)
__android_log_write(ANDROID_LOG_ERROR, "set","h264_encoder");
if (!codec) {
fprintf(stderr, "codec not found\n");
__android_log_write(ANDROID_LOG_ERROR, "codec", "not found");
}
__android_log_write(ANDROID_LOG_ERROR, "codec", "alloc-contest3");
c= avcodec_alloc_context3(codec);
if(c == NULL)
__android_log_write(ANDROID_LOG_ERROR, "avcodec","context-null");
picture= av_frame_alloc();
if(picture == NULL)
__android_log_write(ANDROID_LOG_ERROR, "picture","context-null");
c->bit_rate = 400000;
c->height = 800;
c->time_base= (AVRational){1,25};
c->gop_size = 10;
c->max_b_frames=1;
c->pix_fmt = AV_PIX_FMT_YUV420P;
outbuf_size = 768000;
c->width = 480;
size = (c->width * c->height);
if (avcodec_open2(c, codec,NULL) < 0) {
__android_log_write(ANDROID_LOG_ERROR, "codec", "could not open");
}
ret = av_image_alloc(picture->data, picture->linesize, c->width, c->height,
c->pix_fmt, 32);
if (ret < 0) {
__android_log_write(ANDROID_LOG_ERROR, "image","alloc-failed");
fprintf(stderr, "could not alloc raw picture buffer\n");
}
picture->format = c->pix_fmt;
picture->width = c->width;
picture->height = c->height;
return 0;
}
encodeframe()-called in a while loop
int Java_com_my_package_encodeframe (JNIEnv *env, jobject thiz,jbyteArray buffer) {
jbyte *temp= (*env)->GetByteArrayElements(env, buffer, 0);
Output = (char *)temp;
const uint8_t * const inData[1] = { Output };
const int inLinesize[1] = { 2*c->width };
//swscale should implement here
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
fflush(stdout);
picture->data[0] = Output;
ret = avcodec_encode_video2(c, &pkt, picture,&got_output);
fprintf(stderr,"ret = %d, got-out = %d \n",ret,got_output);
if (ret < 0) {
__android_log_write(ANDROID_LOG_ERROR, "error","encoding");
if(got_output > 0)
__android_log_write(ANDROID_LOG_ERROR, "got_output","is non-zero");
}
if (got_output) {
fprintf(stderr,"encoding frame %3d (size=%5d): (ret=%d)\n", 1, pkt.size,ret);
fprintf(stderr,"before caling decode");
decode_inline(&pkt); //function that decodes right after the encode
fprintf(stderr,"after caling decode");
av_free_packet(&pkt);
}
fprintf(stderr,"y val: %d \n",y);
(*env)->ReleaseByteArrayElements(env, buffer, Output, 0);
return ((ret));
}
decode_inline() function
decode_inline(AVPacket *avpkt){
AVCodec *codec;
AVCodecContext *c = NULL;
int frame, got_picture, len = -1,temp=0;
AVFrame *rawFrame, *rgbFrame;
uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
char buf[1024];
char rawBuf[768000],rgbBuf[768000];
struct SwsContext *sws_ctx;
memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
avcodec_register_all();
c= avcodec_alloc_context3(codec);
if(c == NULL)
__android_log_write(ANDROID_LOG_ERROR, "avcodec","context-null");
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
fprintf(stderr, "codec not found\n");
fprintf(stderr, "codec = %p \n", codec);
}
c->pix_fmt = AV_PIX_FMT_YUV420P;
c->width = 480;
c->height = 800;
rawFrame = av_frame_alloc();
rgbFrame = av_frame_alloc();
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
sws_ctx = sws_getContext(c->width, c->height,/*PIX_FMT_RGB565BE*/
PIX_FMT_YUV420P, c->width, c->height, AV_PIX_FMT_RGB565/*PIX_FMT_YUV420P*/,
SWS_BILINEAR, NULL, NULL, NULL);
frame = 0;
unsigned short *decodedpixels = &rawBuf;
rawFrame->data[0] = &rawBuf;
rgbFrame->data[0] = &rgbBuf;
fprintf(stderr,"size of avpkt %d \n",avpkt->size);
temp = avpkt->size;
while (temp > 0) {
len = avcodec_decode_video2(c, rawFrame, &got_picture, avpkt);
if (len < 0) {
fprintf(stderr, "Error while decoding frame %d\n", frame);
exit(1);
}
temp -= len;
avpkt->data += len;
if (got_picture) {
printf("saving frame %3d\n", frame);
fflush(stdout);
//TODO
//memcpy(decodedpixels,rawFrame->data[0],rawFrame->linesize[0]);
// decodedpixels +=rawFrame->linesize[0];
frame++;
}
}
avcodec_close(c);
av_free(c);
//free(rawBuf);
//free(rgbBuf);
av_frame_free(&rawFrame);
av_frame_free(&rgbFrame);
}
The log i get
For the decode_inline() function:
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] non-existing PPS 0 referenced
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] decode_slice_header error
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] non-existing PPS 0 referenced
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] decode_slice_header error
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] non-existing PPS 0 referenced
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] decode_slice_header error
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] non-existing PPS 0 referenced
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] decode_slice_header error
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] non-existing PPS 0 referenced
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] decode_slice_header error
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] non-existing PPS 0 referenced
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] decode_slice_header error
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] non-existing PPS 0 referenced
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] decode_slice_header error
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] non-existing PPS 0 referenced
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] decode_slice_header error
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] non-existing PPS 0 referenced
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] decode_slice_header error
01-02 14:50:50.160: I/stderr(3407): [h264 @ 0x8db540] Invalid mix of idr and non-idr slices
01-02 14:50:50.160: I/stderr(3407): Error while decoding frame 0
Edit: Changing GOP value:
If i change c->gop_size = 3;
as expected it emits one I frame
every three frames. The non-existing PPS 0 referenced
message is not there for in every third execution, but all other have this message
回答1:
In your decode_inline() method, right after specifying the size, here are some codec parameters that you can play with to get the higher quality. I filled in the values to get you started:
c->gop_size = 10; // one intra frame every ten frames
c->max_b_frames = 1; // max # of b-frames
c->keyint_min = 1; // min GOP size
c->i_quant_factor = (float)0.71; // qscale factor between P and I frames
c->b_frame_strategy = 20;
c->refs = 4; // number of reference frames
c->trellis = 1; // trellis RD Quantization
c->qcompress = (float)0.8;
c->qmin = 20; // min quantizer
c->qmax = 51; // max quantizer
c->max_qdiff = 4; // max quantizer difference between frames
Let me know how it goes.
来源:https://stackoverflow.com/questions/21169040/android-h264-decode-non-existing-pps-0-referenced