Libmix: Fixed surface pool allocation
BZ: 4928, 4144
Changes to frame manager and AVC object to correctly support AVC specification
Change-Id: Id80920257f08fbec7b0c8d58eed12d98af8fe51c
diff --git a/mix_video/src/mixframemanager.cpp b/mix_video/src/mixframemanager.cpp
index adfc53e..cbd2439 100644
--- a/mix_video/src/mixframemanager.cpp
+++ b/mix_video/src/mixframemanager.cpp
@@ -44,6 +44,7 @@
,next_frame_picnumber(0)
,max_enqueue_size(MIX_MAX_ENQUEUE_SIZE)
,max_picture_number((uint32)-1)
+ ,dpb_size((uint32)-1)
,ref_count(1) {
}
@@ -186,6 +187,15 @@
return MIX_RESULT_SUCCESS;
}
+MIX_RESULT mix_framemanager_set_dpb_size(
+ MixFrameManager *fm, uint32 num) {
+ fm->mLock.lock();
+ fm->dpb_size = num < MIX_MAX_ENQUEUE_SIZE ? num : MIX_MAX_ENQUEUE_SIZE;
+ LOG_V("dpb is %d\n", fm->dpb_size);
+ fm->mLock.unlock();
+ return MIX_RESULT_SUCCESS;
+}
+
MIX_RESULT mix_framemanager_flush(MixFrameManager *fm) {
MixVideoFrame *frame = NULL;
@@ -466,11 +476,15 @@
{
int i, len;
MixVideoFrame* p;
+ MixVideoFrame* outp;
+ int outpicnum;
+ int prevpicnum;
uint32 picnum;
uint32 next_picnum_pending;
int least_poc_index;
uint32 least_poc;
+ uint32 maxframeinqueue;
len = j_slist_length(fm->frame_list);
@@ -479,61 +493,56 @@
least_poc_index = -1;
least_poc = (uint32)-1;
- for (i = 0; i < len; )
+ if ((fm->dpb_size == -1) || (fm->dpb_size == len))
{
- p = (MixVideoFrame*)j_slist_nth_data(fm->frame_list, i);
- mix_videoframe_get_displayorder(p, &picnum);
- if (picnum == fm->next_frame_picnumber)
- {
- fm->frame_list = j_slist_remove(fm->frame_list, p);
- mix_framemanager_update_timestamp(fm, p);
- *mvf = p;
- LOG_V("frame is dequeued, poc = %d.\n", fm->next_frame_picnumber);
- fm->next_frame_picnumber++;
- //if (fm->next_frame_picnumber == fm->max_picture_number)
- // fm->next_frame_picnumber = 0;
- return MIX_RESULT_SUCCESS;
- }
-
- if(picnum == 0) {
- if(i == 0) {
- fm->next_frame_picnumber = 0;
- } else {
- fm->next_frame_picnumber = least_poc;
- i = least_poc_index;
- }
- continue;
- }
- if(picnum < least_poc) {
- least_poc = picnum;
- least_poc_index = i;
- LOG_V("least_poc_index = %d\n", least_poc_index);
- }
-
- ++i;
-
- if (picnum > fm->next_frame_picnumber &&
- picnum < next_picnum_pending)
- {
- next_picnum_pending = picnum;
- }
-
- if (picnum < fm->next_frame_picnumber &&
- fm->next_frame_picnumber - picnum < 8)
- {
- // the smallest value of "max_pic_order_cnt_lsb_minus4" is 16. If the distance of "next frame pic number"
- // to the pic number in the list is less than half of 16, it is safe to assume that pic number
- // is reset when a new IDR is encoded. (where pic numbfer of top or bottom field must be 0, subclause 8.2.1).
- LOG_V("picture number is reset to %d, next pic number is %d, next pending number is %d.\n",
- picnum, fm->next_frame_picnumber, next_picnum_pending);
- break;
- }
+ maxframeinqueue = len;
+ maxframeinqueue = (maxframeinqueue < (MIX_MAX_ENQUEUE_SIZE + 1)) ? maxframeinqueue : (MIX_MAX_ENQUEUE_SIZE + 1);
+ }
+ else
+ {
+ maxframeinqueue = 0;
}
+ if (maxframeinqueue)
+ {
+ p = (MixVideoFrame*)j_slist_nth_data(fm->frame_list, 0);
+ mix_videoframe_get_displayorder(p, &picnum);
+ outpicnum = picnum;
+ prevpicnum = picnum;
+ outp = p;
+
+ for (i = 1; i < maxframeinqueue;i++ )
+ {
+ p = (MixVideoFrame*)j_slist_nth_data(fm->frame_list, i);
+ mix_videoframe_get_displayorder(p, &picnum);
+
+ if (picnum ==0)
+ {
+ break;
+ }
+ else if (picnum < outpicnum)
+ {
+ outpicnum = picnum;
+ outp = p;
+ prevpicnum = picnum;
+ }
+ else //(picnum >= outpicnum)
+ {
+ prevpicnum = picnum;
+ }
+ }
+
+ fm->frame_list = j_slist_remove(fm->frame_list, (void *)outp);
+ mix_framemanager_update_timestamp(fm, outp);
+ *mvf = outp;
+
+
+ return MIX_RESULT_SUCCESS;
+ }
if (len <= fm->max_enqueue_size && fm->eos == FALSE)
{
LOG_V("No frame is dequeued. Expected POC = %d, next pending POC = %d. (List size = %d)\n",
- fm->next_frame_picnumber, next_picnum_pending, len);
+ fm->next_frame_picnumber, next_picnum_pending, len);
return MIX_RESULT_FRAME_NOTAVAIL;
}
@@ -541,7 +550,7 @@
if (next_picnum_pending != (uint32)-1)
{
LOG_V("picture number has gap, jumping from %d to %d.\n",
- fm->next_frame_picnumber, next_picnum_pending);
+ fm->next_frame_picnumber, next_picnum_pending);
fm->next_frame_picnumber = next_picnum_pending;
goto retry;
@@ -549,7 +558,7 @@
// picture number roll-over
LOG_V("picture number is rolled over, resetting next picnum from %d to 0.\n",
- fm->next_frame_picnumber);
+ fm->next_frame_picnumber);
fm->next_frame_picnumber = 0;
goto retry;
diff --git a/mix_video/src/mixframemanager.h b/mix_video/src/mixframemanager.h
index 684857d..ca49ef0 100644
--- a/mix_video/src/mixframemanager.h
+++ b/mix_video/src/mixframemanager.h
@@ -52,6 +52,7 @@
int max_enqueue_size;
uint32 max_picture_number;
uint32 ref_count;
+ int dpb_size;
};
@@ -119,6 +120,8 @@
MIX_RESULT mix_framemanager_set_max_picture_number(
MixFrameManager *fm, uint32 num);
+MIX_RESULT mix_framemanager_set_dpb_size(
+ MixFrameManager *fm, uint32 num);
/*
* Get Display Order Mode
diff --git a/mix_video/src/mixvideoformat_h264.cpp b/mix_video/src/mixvideoformat_h264.cpp
index 0bbe19a..158c456 100644
--- a/mix_video/src/mixvideoformat_h264.cpp
+++ b/mix_video/src/mixvideoformat_h264.cpp
@@ -349,6 +349,7 @@
Unlock();
//Call Frame Manager with _eos()
ret = mix_framemanager_eos(this->framemgr);
+ mix_framemanager_set_dpb_size(this->framemgr, -1);
LOG_V( "End\n");
return ret;
}
@@ -484,10 +485,94 @@
num_ref_pictures = data->codec_data->num_ref_frames;
}
+ int pic_size;
+ int size = 3;
+ if (data)
+ {
+ pic_size = (data->pic_data[0].pic_parms->picture_width_in_mbs_minus1 + 1) * (data->pic_data[0].pic_parms->picture_height_in_mbs_minus1 + 1) * (data->codec_data->frame_mbs_only_flag?1:2) * 384;
+
+ switch (data->codec_data->level_idc)
+ {
+ case 9:
+ size = 152064;
+ break;
+ case 10:
+ size = 152064;
+ break;
+ case 11:
+ size = 345600;
+ break;
+ case 12:
+ size = 912384;
+ break;
+ case 13:
+ size = 912384;
+ break;
+ case 20:
+ size = 912384;
+ break;
+ case 21:
+ size = 1824768;
+ break;
+ case 22:
+ size = 3110400;
+ break;
+ case 30:
+ size = 3110400;
+ break;
+ case 31:
+ size = 6912000;
+ break;
+ case 32:
+ size = 7864320;
+ break;
+ case 40:
+ size = 12582912;
+ break;
+ case 41:
+ size = 12582912;
+ break;
+ case 42:
+ size = 13369344;
+ break;
+ case 50:
+ size = 42393600;
+ break;
+ case 51:
+ size = 70778880;
+ break;
+ default:
+ //error ("undefined level", 500);
+ break;
+ }
+
+ if (pic_size)
+ {
+ size /= pic_size;
+ if (size == 0)
+ {
+ size = 3;
+ }
+ else if (size > 16)
+ {
+ size = 15;
+ }
+ }
+ else
+ {
+ size = 3;
+ }
+ }
+
+ mix_framemanager_set_dpb_size(this->framemgr, size);
+
//Adding 1 to work around VBLANK issue, and another 1 to compensate cached frame that
// will not start decoding until a new frame is received.
- this->va_num_surfaces = 1 + 1 + this->extra_surfaces +
- (((num_ref_pictures + 3) < MIX_VIDEO_H264_SURFACE_NUM) ? (num_ref_pictures + 3) : MIX_VIDEO_H264_SURFACE_NUM);
+ this->va_num_surfaces = 1 + 1 + this->extra_surfaces + (((size + 3) <
+ MIX_VIDEO_H264_SURFACE_NUM) ?
+ (size + 3)
+ : MIX_VIDEO_H264_SURFACE_NUM);
+ this->va_num_surfaces = this->va_num_surfaces > 24 ? 24 : this->va_num_surfaces;
this->va_surfaces =
reinterpret_cast<VASurfaceID*>(malloc(sizeof(VASurfaceID)*this->va_num_surfaces));